Skip to content

Commit

Permalink
feat: switch ContentType from options pattern to fluent
Browse files Browse the repository at this point in the history
  • Loading branch information
rvagg committed Sep 8, 2023
1 parent b968d29 commit e2c362f
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 88 deletions.
55 changes: 28 additions & 27 deletions http/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,19 @@ var (
ResponseChunkDelimeter = []byte("0\r\n") // An http/1.1 chunk delimeter, used for specifying an early end to the response
)

// ContentType represents a Content-Type descriptor for use with the response
// Content-Type header or the request Accept header specifically for
// Trustless Gateway requests and responses.
type ContentType struct {
Mime string
MimeType string
Order ContentTypeOrder
Duplicates bool
Quality float32
}

func (ct ContentType) String() string {
sb := strings.Builder{}
sb.WriteString(ct.Mime)
sb.WriteString(ct.MimeType)
sb.WriteString(";version=")
sb.WriteString(MimeTypeCarVersion)
sb.WriteString(";order=")
Expand All @@ -51,55 +54,53 @@ func (ct ContentType) String() string {
return sb.String()
}

type ContentTypeOption func(ct *ContentType)
// WithOrder returns a new ContentType with the specified order.
func (ct ContentType) WithOrder(order ContentTypeOrder) ContentType {
ct.Order = order
return ct
}

func WithContentTypeOrder(order ContentTypeOrder) ContentTypeOption {
return func(ct *ContentType) {
ct.Order = order
}
// WithDuplicates returns a new ContentType with the specified duplicates.
func (ct ContentType) WithDuplicates(duplicates bool) ContentType {
ct.Duplicates = duplicates
return ct
}

func WithContentTypeDuplicates(duplicates bool) ContentTypeOption {
return func(ct *ContentType) {
ct.Duplicates = duplicates
}
// WithMime returns a new ContentType with the specified mime type.
func (ct ContentType) WithMimeType(mime string) ContentType {
ct.MimeType = mime
return ct
}

func WithContentTypeQuality(quality float32) ContentTypeOption {
return func(ct *ContentType) {
ct.Quality = quality
}
// WithQuality returns a new ContentType with the specified quality.
func (ct ContentType) WithQuality(quality float32) ContentType {
ct.Quality = quality
return ct
}

func NewContentType(opt ...ContentTypeOption) ContentType {
ct := ContentType{
Mime: MimeTypeCar,
func DefaultContentType() ContentType {
return ContentType{
MimeType: MimeTypeCar,
Order: DefaultOrder,
Duplicates: DefaultIncludeDupes,
Quality: 1,
}
for _, o := range opt {
o(&ct)
}
return ct
}

// ResponseContentTypeHeader returns the value for the Content-Type header for a
// Trustless Gateway response which will vary depending on whether duplicates
// are included or not. Otherwise, the header is the same for all responses.
//
// Deprecated: Use NewContentType().String() instead.
// Deprecated: Use DefaultContentType().WithDuplicates(duplicates).String() instead.
func ResponseContentTypeHeader(duplicates bool) string {
ct := NewContentType()
ct.Duplicates = duplicates
return ct.String()
return DefaultContentType().WithDuplicates(duplicates).String()
}

// RequestAcceptHeader returns the value for the Accept header for a Trustless
// Gateway request which will vary depending on whether duplicates are included
// or not. Otherwise, the header is the same for all requests.
//
// Deprecated: Use NewContentType().String() instead.
// Deprecated: Use DefaultContentType().WithDuplicates(duplicates).String() instead.
func RequestAcceptHeader(duplicates bool) string {
return ResponseContentTypeHeader(duplicates)
}
12 changes: 6 additions & 6 deletions http/constants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ func TestContentType(t *testing.T) {
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=n", trustlesshttp.ResponseContentTypeHeader(false))
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=n", trustlesshttp.RequestAcceptHeader(false))

req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=y", trustlesshttp.NewContentType().String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=y;q=0.8", trustlesshttp.NewContentType(trustlesshttp.WithContentTypeQuality(0.8)).String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=y;q=0.333", trustlesshttp.NewContentType(trustlesshttp.WithContentTypeQuality(1.0/3.0)).String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=y", trustlesshttp.NewContentType(trustlesshttp.WithContentTypeQuality(-1.0)).String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=n", trustlesshttp.NewContentType(trustlesshttp.WithContentTypeDuplicates(false)).String())
req.Equal("application/vnd.ipld.car;version=1;order=unk;dups=n", trustlesshttp.NewContentType(trustlesshttp.WithContentTypeDuplicates(false), trustlesshttp.WithContentTypeOrder(trustlesshttp.ContentTypeOrderUnk)).String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=y", trustlesshttp.DefaultContentType().String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=y;q=0.8", trustlesshttp.DefaultContentType().WithQuality(0.8).String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=y;q=0.333", trustlesshttp.DefaultContentType().WithQuality(1.0/3.0).String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=y", trustlesshttp.DefaultContentType().WithQuality(-1.0).String())
req.Equal("application/vnd.ipld.car;version=1;order=dfs;dups=n", trustlesshttp.DefaultContentType().WithDuplicates(false).String())
req.Equal("application/vnd.ipld.car;version=1;order=unk;dups=n", trustlesshttp.DefaultContentType().WithDuplicates(false).WithOrder(trustlesshttp.ContentTypeOrderUnk).String())
}
5 changes: 2 additions & 3 deletions http/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func CheckFormat(req *http.Request) (ContentType, error) {
}

if validFormat {
return NewContentType(), nil // default is acceptable in this case (no accept but format=car)
return DefaultContentType(), nil // default is acceptable in this case (no accept but format=car)
}

return ContentType{}, fmt.Errorf("neither a valid Accept header nor format parameter were provided")
Expand Down Expand Up @@ -140,8 +140,7 @@ func parseContentType(header string, strictType bool) (ContentType, bool) {
typeParts := strings.Split(header, ";")
mime := strings.TrimSpace(typeParts[0])
if mime == MimeTypeCar || (!strictType && (mime == "*/*" || mime == "application/*")) {
contentType := NewContentType()
contentType.Mime = mime
contentType := DefaultContentType().WithMimeType(mime)
// parse additional car attributes outlined in IPIP-412
// https://specs.ipfs.tech/http-gateways/trustless-gateway/
for _, nextPart := range typeParts[1:] {
Expand Down
Loading

0 comments on commit e2c362f

Please sign in to comment.