Skip to content

Commit

Permalink
feat(gateway): parse ipip-402 Accept Header params
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Jun 22, 2023
1 parent a9794ec commit 2f2e7f2
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 6 deletions.
13 changes: 11 additions & 2 deletions gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ func (i ImmutablePath) IsValid() error {
var _ path.Path = (*ImmutablePath)(nil)

type CarParams struct {
Range *DagByteRange
Scope DagScope
Range *DagByteRange
Scope DagScope
Order DagOrder
Duplicates *bool
}

// DagByteRange describes a range request within a UnixFS file. "From" and
Expand Down Expand Up @@ -189,6 +191,13 @@ const (
DagScopeBlock DagScope = "block"
)

type DagOrder string

const (
DagOrderDFS DagOrder = "dfs"
DagOrderUnknown DagOrder = "unk"
)

type ContentPathMetadata struct {
PathSegmentRoots []cid.Cid
LastSegment path.Resolved
Expand Down
26 changes: 24 additions & 2 deletions gateway/handler_car.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (i *handler) serveCAR(ctx context.Context, w http.ResponseWriter, r *http.R
return false
}

params, err := getCarParams(r)
params, err := getCarParams(r, rq.responseParams)
if err != nil {
i.webError(w, r, err, http.StatusBadRequest)
return false
Expand Down Expand Up @@ -113,7 +113,7 @@ func (i *handler) serveCAR(ctx context.Context, w http.ResponseWriter, r *http.R
return true
}

func getCarParams(r *http.Request) (CarParams, error) {
func getCarParams(r *http.Request, formatParams map[string]string) (CarParams, error) {
queryParams := r.URL.Query()
rangeStr, hasRange := queryParams.Get(carRangeBytesKey), queryParams.Has(carRangeBytesKey)
scopeStr, hasScope := queryParams.Get(carTerminalElementTypeKey), queryParams.Has(carTerminalElementTypeKey)
Expand All @@ -140,6 +140,28 @@ func getCarParams(r *http.Request) (CarParams, error) {
params.Scope = DagScopeAll
}

switch order := DagOrder(formatParams["order"]); order {
case DagOrderUnknown, DagOrderDFS:
params.Order = order
case "":
params.Order = DagOrderUnknown
default:
return CarParams{}, fmt.Errorf("unsupported order %s", order)
}

switch dups := formatParams["dups"]; dups {
case "y":
v := true
params.Duplicates = &v
case "n":
v := false
params.Duplicates = &v
case "":
// Acceptable, we do not set anything.
default:
return CarParams{}, fmt.Errorf("unsupported dups %s", dups)
}

return params, nil
}

Expand Down
42 changes: 40 additions & 2 deletions gateway/handler_car_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestCarParams(t *testing.T) {
}
for _, test := range tests {
r := mustNewRequest(t, http.MethodGet, "http://example.com/?"+test.query, nil)
params, err := getCarParams(r)
params, err := getCarParams(r, map[string]string{})
if test.expectedError {
assert.Error(t, err)
} else {
Expand Down Expand Up @@ -60,7 +60,7 @@ func TestCarParams(t *testing.T) {
}
for _, test := range tests {
r := mustNewRequest(t, http.MethodGet, "http://example.com/?"+test.query, nil)
params, err := getCarParams(r)
params, err := getCarParams(r, map[string]string{})
if test.hasError {
assert.Error(t, err)
} else {
Expand All @@ -73,6 +73,44 @@ func TestCarParams(t *testing.T) {
}
}
})

t.Run("order and duplicates parsing", func(t *testing.T) {
t.Parallel()

T := true
F := false

tests := []struct {
acceptHeader string
expectedOrder DagOrder
expectedDuplicates *bool
}{
{"application/vnd.ipld.car; order=dfs; dups=y", DagOrderDFS, &T},
{"application/vnd.ipld.car; order=unk; dups=n", DagOrderUnknown, &F},
{"application/vnd.ipld.car; order=unk", DagOrderUnknown, nil},
{"application/vnd.ipld.car; dups=y", DagOrderUnknown, &T},
{"application/vnd.ipld.car; dups=n", DagOrderUnknown, &F},
{"application/vnd.ipld.car", DagOrderUnknown, nil},
}
for _, test := range tests {
r := mustNewRequest(t, http.MethodGet, "http://example.com/", nil)
r.Header.Set("Accept", test.acceptHeader)

mediaType, formatParams, err := customResponseFormat(r)
assert.NoError(t, err)
assert.Equal(t, carResponseFormat, mediaType)

params, err := getCarParams(r, formatParams)
assert.NoError(t, err)
require.Equal(t, test.expectedOrder, params.Order)

if test.expectedDuplicates == nil {
require.Nil(t, params.Duplicates)
} else {
require.Equal(t, *test.expectedDuplicates, *params.Duplicates)
}
}
})
}

func TestGetCarEtag(t *testing.T) {
Expand Down

0 comments on commit 2f2e7f2

Please sign in to comment.