Skip to content
This repository has been archived by the owner on Jun 30, 2020. It is now read-only.

Filter list of acceptable headers; use default if the client accepts everything #81

Merged
merged 6 commits into from
Aug 22, 2017

Conversation

mlambley
Copy link

@mlambley mlambley commented Aug 15, 2017

Added a priorities member variable, which allows the dev to filter the list of acceptable headers.

Usage:

//Code
Middleware::FormatNegotiator()
    ->setPriorities(['json', 'zip'])
    ->defaultFormat('json')

//Request header
Accept: application/pdf, application/zip

//Result: 
FormatNegotiator::getFormat($request) === "zip"

getFromHeader will return null if the accept header is either missing, or set to accept everything. This will allow the default to be used instead.

Usage:

//Code
Middleware::FormatNegotiator()
    ->defaultFormat('json')

//Request header
Accept: */*

//Result: 
FormatNegotiator::getFormat($request) === "json"

…e list of acceptable headers.

getFromHeader will return null if the accept header is either missing, or set to accept everything. This will allow the default to be used instead.
@oscarotero
Copy link
Owner

The PSR-15 version of this middeware accept a list of formats in the constructor:
https://github.com/middlewares/negotiation#contenttype
This allows to define not only the formats but also the priority. I think it's a more simple and elegant solution.

@mlambley
Copy link
Author

Hi Oscar, I might just use the PSR-15 one instead.

I've just updated this PR to make $priorities a constructor parameter, bringing that newer version's functionality into this version. Do you still want it?

@mlambley
Copy link
Author

Quick note: I've given up on trying to retrofit PSR-15 middlewares into Slim (the framework I'm using). Apparently support will be in a later version. So I will need to use this PSR-7 FormatNegotiator.

@oscarotero
Copy link
Owner

Hi, @mlambley
What I meant was the constructor argument were the available formats, not the priorities. For example, if you only want to support json:

Middleware::FormatNegotiator([
    'json' => [['json'], ['application/json', 'text/json', 'application/x-json']],
])

This prevent the situation where you customize the desired priorities but the formats are not available, which would be confused.
In addition to that, the defaultFormat could be always the first format provided.

@mlambley
Copy link
Author

I figure that you would want to keep the existing addFormat and defaultFormat functions, to not introduce a breaking change, even though the functionality is replicated.

I have not set the default format to be the first item in the list, on the assumption that we will not be removing the defaultFormat function.

@oscarotero
Copy link
Owner

Yes, I don't want to introduce breaking changes here. addFormat and defaultFormat functions will continue to exist. What I suggested is:

  • Modify __construct to include the desired formats. The first value of the array is the default value. Example:
    $this->defaultFormat = key($this->formats);
    Because the first value of the default formats is html, the default value is html, as it works now. So, no breaking changes here.
  • addFormat just add more formats at the end of the array. Nothing changes here
  • defaultFormat just change the value of the default format. Additionally, I think the default format should be moved to the first place. For example, for json:
    $default = $this->formats['json'];
    $this->formats = ['json' => $default] + $this->formats;
    In this way, * or */* would return the first format (the default) by the headers negotiation.

…fore we no longer need to check for "all" in getFromHeader.

If the user explicitly sets default format to be null, then the system will generate a 406 Not Acceptable response if no types match. For example:

```
//Code
Middleware::FormatNegotiator([
    'json' => [['json'], ['application/json', 'text/json', 'application/x-json']],
    'zip' => [['zip'], ['application/zip', 'application/x-zip', 'application/x-zip-compressed']]
])
->defaultFormat(null)

//Header:
Accept: application/pdf

//Result
406 Not Acceptable
```

Readme updated to reflect.
@mlambley
Copy link
Author

mlambley commented Aug 22, 2017

Hi Oscar, I've introduced an option for it to generate a 406 Not Acceptable response in order for it to work with my server. Please let me know if this, and the other changes you requested, are ok.

I'm hoping that you won't consider this change to be breaking, since the behaviour of setting default to null is currently undefined.

@oscarotero oscarotero merged commit f173bc2 into oscarotero:master Aug 22, 2017
@oscarotero
Copy link
Owner

I think it's good. In fact, I have a similar feature in the PSR-15 version
Thanks 👍

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants