@@ -2,6 +2,7 @@ package gateway
2
2
3
3
import (
4
4
"context"
5
+ "encoding/binary"
5
6
"fmt"
6
7
"io"
7
8
"net/http"
@@ -166,20 +167,18 @@ func buildCarParams(r *http.Request, contentTypeParams map[string]string) (CarPa
166
167
}
167
168
168
169
// optional dups from IPIP-412
169
- if dups := NewDuplicateBlocksPolicy (contentTypeParams ["dups" ]); dups != DuplicateBlocksUnspecified {
170
- switch dups {
171
- case DuplicateBlocksExcluded , DuplicateBlocksIncluded :
172
- params .Duplicates = dups
173
- default :
174
- return CarParams {}, fmt .Errorf ("unsupported application/vnd.ipld.car content type dups parameter: %q" , dups )
175
- }
176
- } else {
170
+ dups , err := NewDuplicateBlocksPolicy (contentTypeParams ["dups" ])
171
+ if err != nil {
172
+ return CarParams {}, err
173
+ }
174
+ if dups == DuplicateBlocksUnspecified {
177
175
// when duplicate block preference is not specified, we set it to
178
176
// false, as this has always been the default behavior, we should
179
177
// not break legacy clients, and responses to requests made via ?format=car
180
178
// should benefit from block deduplication
181
- params . Duplicates = DuplicateBlocksExcluded
179
+ dups = DuplicateBlocksExcluded
182
180
}
181
+ params .Duplicates = dups
183
182
184
183
return params , nil
185
184
}
@@ -226,31 +225,43 @@ func getCarRootCidAndLastSegment(imPath path.ImmutablePath) (cid.Cid, string, er
226
225
}
227
226
228
227
func getCarEtag (imPath path.ImmutablePath , params CarParams , rootCid cid.Cid ) string {
229
- data := imPath .String ()
228
+ h := xxhash .New ()
229
+ h .WriteString (imPath .String ())
230
+ // be careful with hashes here, we need boundaries and per entry salt, we don't want a request that has:
231
+ // - scope = dfs
232
+ // and:
233
+ // - order = dfs
234
+ // to result in the same hash because if we just do hash(scope + order) they would both yield hash("dfs").
230
235
if params .Scope != DagScopeAll {
231
- data += string (params .Scope )
236
+ h .WriteString ("\x00 scope=" )
237
+ h .WriteString (string (params .Scope ))
232
238
}
233
239
234
240
// 'order' from IPIP-412 impact Etag only if set to something else
235
241
// than DFS (which is the implicit default)
236
242
if params .Order != DagOrderDFS {
237
- data += string (params .Order )
243
+ h .WriteString ("\x00 order=" )
244
+ h .WriteString (string (params .Order ))
238
245
}
239
246
240
247
// 'dups' from IPIP-412 impact Etag only if 'y'
241
- if dups := params .Duplicates . String () ; dups == "y" {
242
- data += dups
248
+ if dups := params .Duplicates ; dups == DuplicateBlocksIncluded {
249
+ h . WriteString ( " \x00 dups=y" )
243
250
}
244
251
245
252
if params .Range != nil {
246
253
if params .Range .From != 0 || params .Range .To != nil {
247
- data += strconv .FormatInt (params .Range .From , 10 )
254
+ h .WriteString ("\x00 range=" )
255
+ var b [8 ]byte
256
+ binary .LittleEndian .PutUint64 (b [:], uint64 (params .Range .From ))
257
+ h .Write (b [:])
248
258
if params .Range .To != nil {
249
- data += strconv .FormatInt (* params .Range .To , 10 )
259
+ binary .LittleEndian .PutUint64 (b [:], uint64 (* params .Range .To ))
260
+ h .Write (b [:])
250
261
}
251
262
}
252
263
}
253
264
254
- suffix := strconv .FormatUint (xxhash .Sum64 ([] byte ( data ) ), 32 )
265
+ suffix := strconv .FormatUint (h .Sum64 (), 32 )
255
266
return `W/"` + rootCid .String () + ".car." + suffix + `"`
256
267
}
0 commit comments