8000 Handle wildcard "+" segments by weierophinney · Pull Request #92 · willdurand/Negotiation · GitHub
[go: up one dir, main page]

Skip to content

Handle wildcard "+" segments #92

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

weierophinney
Copy link
Contributor

A relatively common way to allow negotation to multiple serialization structures for a single media type is to use "+" notation within the mediatype:

  • application/vnd.book+json: JSON serialization of application/vnd.book mediatype.
  • application/vnd.book+xml: XML serialization of application/vnd.book mediatype.

In particular, this is useful for determining what general serialization is used for an incoming request in order to select an appropriate deserializer.

With the current 2.X branch, I expected the following to work:

use Negotiation\Negotiator;

$mediaType = (new Negotiator)->getBest($accept, [
    'application/json',
    'application/*+json',
    'application/xml',
    'application/*+xml',
]);

However, it failed on each of the cases listed above.

This patch provides additional negotiation routines within Negotiation\Negotiator::match in order to allow such negotiation to work as expected.

@willdurand willdurand self-requested a review May 3, 2017 15:29
@willdurand
Copy link
Owner

Hi @weierophinney, thanks for this great patch!

I will fix the Appveyor setup and trigger the build again for this PR but looks good to me :)

$ab = $accept->getBasePart();
$pb = $priority->getBasePart();
$acceptBase = $accept->getBasePart();
$priorityBase = $priority->getBasePart();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed these variable names as I was confused by the two-character names when attempting to make my changes. I can revert these if desired, but I think they make the intent far clearer.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, perfect

if (($acceptBase === '*' || $baseEqual)
&& ($acceptSub === '*' || $subEqual)
&& count($intersection) === count($accept->getParameters())
) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I split this condition across multiple lines to better understand the precedence of operations.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

$score = 100 * $baseEqual + 10 * $subEqual + count($intersection);

return new Match($accept->getQuality() * $priority->getQuality(), $score, $index);
}

if (!strstr($acceptSub, '+') || !strstr($prioritySub, '+')) {
return null;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If either the accept header or the priority do not have + segments, we can return immediately without further checks, retaining the previous workflow.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👌

@willdurand willdurand force-pushed the feature/plus-part-matching branch from a04be91 to b737a69 Compare May 4, 2017 12:05
A relatively common way to allow negotation to multiple serialization
structures for a single media type is to use "+" notation within the
mediatype:

- `application/vnd.book+json`: JSON serialization of
  `application/vnd.book` mediatype.
- `application/vnd.book+xml`: XML serialization of
  `application/vnd.book` mediatype.

In particular, this is useful for determining what _general_
serialization is used for an incoming request in order to select an
appropriate deserializer.

With the current 2.X branch, I expected the following to work:

```php
use Negotiation\Negotiator;

$mediaType = (new Negotiator)->getBest($accept, [
    'application/json',
    'application/*+json',
    'application/xml',
    'application/*+xml',
]);
```

However, it failed on each of the cases listed above.

This patch provides additional negotiation routines within
`Negotiation\Negotiator::match` in order to allow such negotiation to
work as expected.
@willdurand willdurand force-pushed the feature/plus-part-matching branch from b737a69 to 01e760c Compare May 4, 2017 12:10
@willdurand willdurand merged commit 154ddcd into willdurand:2.x May 4, 2017
@willdurand
Copy link
Owner

Thanks!

@willdurand
Copy link
Owner

Released 2.3.0 with this feature!

@meyerbaptiste
Copy link
meyerbaptiste commented May 4, 2017

Hi @willdurand, @weierophinney! This PR and the new release (2.3) breaks our api-platform/core test suite. See https://travis-ci.org/api-platform/core/jobs/228775063 for example.

I have this accept header: application/hal+json.
My priorities are:

[0] => "application/ld+json"
[1] => "application/hal+json"
[2] => "application/xml"
[3] => "text/xml"
[4] => "application/json"
[5] => "text/html"

Then, the AbstractNegotiator::getBest() method now returns application/ld+json instead of application/hal+json before.

It looks like something is not working properly here, nop? Thanks.

(Ping @dunglas)

@willdurand
Copy link
Owner

ah :(

@weierophinney weierophinney deleted the feature/plus-part-matching branch May 8, 2017 15:53
weierophinney added a commit to weierophinney/Negotiation that referenced this pull request May 8, 2017
Fixes willdurand#93. If there are no wildcard segments in either the subtype or +
segment of either the Accept header or priority, do not attempt to
compare them.

Adds more tests for willdurand#92 as well, using `*` subtypes in both the Accept
header and priorities, to validate that different combinations work as
expected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
0