Skip to content

Instantly share code, notes, and snippets.

@KES777
Created March 23, 2018 15:29
Show Gist options
  • Save KES777/c7b9a2487b98dee19a329102844a1159 to your computer and use it in GitHub Desktop.
Save KES777/c7b9a2487b98dee19a329102844a1159 to your computer and use it in GitHub Desktop.
content negotiation draft
Mojolicious content negotiation gotchas
Let's begin with parts which participate in content negotiation.
First of all there are client requirements and server capabilities.
This is obvious that we should prefer client requirements over server capabilies by default. And, if server (controller's action) wants, it may force {format}.
So picture is next by precedence:
1. Controller's action format preferences
$c->stash->{ format }=XXX
2. Query format
/path/script?format=XXX
3. Path suffix format
/path/script.XXX
4. Accept headers
Accept: XXX
5. Route default format
->get( '/path/script', { format => XXX } )
6. Application default format
sub startup {
...
$app->defaults( format => XXX );
Query format should take precedence over path suffix because it is more
specefic. Also I gather links to other frameworks and wide practice. You can
see them at this gist:
https://gist.github.com/KES777/8f6a32b9cde4404414aadffa8fb2515b
Most important of them are:
1. Rube on rails behavior
2. IBM knowledgebase
3. Enchant/Zendesk API designer
Currently content negotiation in Mojolicious still inconsistent. Test case:
https://gist.github.com/KES777/c56e5043ebde250754df34a473941864
In short: application/route default {format} take precedence over requested
{format} in Accept header or query parameter:
get '/route' => { format => 'xxx' };
$t->get_ok('/route?format=json')->content_is( "json\n" );
got: 'xxx'
expected: 'json'
The problem because of content negotiation even not started:
https://github.com/kraih/mojo/blob/master/lib/Mojolicious/Renderer.pm#L96
Q: When format negotiation must be started?
A: Format negotiation must be started when controller's action do not force {format}
But becuase of the default application/route {format} is merged into stash here:
https://github.com/kraih/mojo/blob/master/lib/Mojolicious/Routes/Pattern.pm#L32
We can not distinguish default {format} from {format} passed from action.
If we could distinguish them:
https://github.com/KES777/mojo/commit/fd9f47307d
We could start content negotiation:
https://github.com/KES777/mojo/commit/8494aef5
This distinguish is very important, because
1. application/route default {format} belongs to server capabilies
2. detected {format} from path suffix belongs to client requirementsjberg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment