Skip to content

Commit

Permalink
✨ feat: add support for parameters in content negotiation (#2678)
Browse files Browse the repository at this point in the history
* ✨ feat: add support for parameters in content negotiation

Attempts to approach the level of support offered by express,
but behavior may differ in unusual corner cases.
Some key behaviors from Express that are implemented:
 - If an offer does not have every parameter listed in the given Accept,
   it is rejected.
 - Parameters do not affect specificity.
 - In a given specificity, more parameters gives greater precedence
 - Parameters are unordered
 - Matching is case-insensitive
 - Surrounding quotes for parameter values are stripped
 - If an Accept type specifies a parameter more than once, the last
   value provided is taken.
 - Parameters after q are not processed.

https://www.rfc-editor.org/rfc/rfc9110#name-parameters

* doc: properly attribute reader.go for validHeaderFieldByte

* fix: remove underscores from fuzz test name

* test(forEachParameter): improve coverage

* doc: add comment clarifying RFC 9110 non-compliance for corner case
  • Loading branch information
nickajacks1 committed Nov 7, 2023
1 parent 426dd3a commit cbcb1ae
Show file tree
Hide file tree
Showing 4 changed files with 625 additions and 64 deletions.
31 changes: 31 additions & 0 deletions docs/api/ctx.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,37 @@ app.Get("/", func(c *fiber.Ctx) error {
})
```

Media-Type parameters are supported.

```go title="Example 3"
// Accept: text/plain, application/json; version=1; foo=bar

app.Get("/", func(c *fiber.Ctx) error {
// Extra parameters in the accept are ignored
c.Accepts("text/plain;format=flowed") // "text/plain;format=flowed"

// An offer must contain all parameters present in the Accept type
c.Accepts("application/json") // ""

// Parameter order and capitalization does not matter. Quotes on values are stripped.
c.Accepts(`application/json;foo="bar";VERSION=1`) // "application/json;foo="bar";VERSION=1"
})
```

```go title="Example 4"
// Accept: text/plain;format=flowed;q=0.9, text/plain
// i.e., "I prefer text/plain;format=flowed less than other forms of text/plain"
app.Get("/", func(c *fiber.Ctx) error {
// Beware: the order in which offers are listed matters.
// Although the client specified they prefer not to receive format=flowed,
// the text/plain Accept matches with "text/plain;format=flowed" first, so it is returned.
c.Accepts("text/plain;format=flowed", "text/plain") // "text/plain;format=flowed"

// Here, things behave as expected:
c.Accepts("text/plain", "text/plain;format=flowed") // "text/plain"
})
```

Fiber provides similar functions for the other accept headers.

```go
Expand Down
Loading

0 comments on commit cbcb1ae

Please sign in to comment.