vlucas / bulletphp

A resource-oriented micro PHP framework
http://bulletphp.com
BSD 3-Clause "New" or "Revised" License
416 stars 50 forks source link

Adding a format handler and allowing default handling #60

Closed omnicolor closed 9 years ago

omnicolor commented 9 years ago

I may just be missing it...

If you add a format handler for a method, do you have to add format handlers for all types that you want to support?

For example, all of my endpoints respond with application/json by default. On one of them, I'd like to be able to send an "Accept: application/schema+json" and get back the JSON schema for that content type. But then making a request without an Accept header returns 406 Not Acceptable.

Is it possible to add a format handler without messing up default behavior?

vlucas commented 9 years ago

A request without an Accept header currently defaults to html, which is why you are getting a 406.

As for custom formats, try this:

$app->format('application/schema+json', function($request) {
    // ... your code here ...
});

I believe it should work with the full MIME type. If I remember correctly, the shorthand 'html', 'json', 'xml', etc. are just handy shortcuts. It's been a while since I coded that section, so I could be wrong. ;)

omnicolor commented 9 years ago

Sorry, I wasn't very clear.

My original handler was:

$app->get(function() use($app) {
    // code to return JSON schema with appropriate headers
});

In this case it would always respond with the JSON schema, no matter what Accept header you send. I've added the format handler like:

$app->get(function() use($app) {
    $app->format('application/schema+json', function() {
        // code to return JSON schema with appropriate headers
    });
    return $app->response(401, 'Unauthorized');
});

What I was expecting was to have a 200 with the JSON schema if you request application/schema+json, or a 401 if you request any other content type.

Instead, I get 200 with the JSON schema if you request the JSON schema, and 406 Not Acceptable no matter what other Accept header you send.

vlucas commented 9 years ago

Yeah, seems like I need a separate wildcard format handler, something like:

$app->get(function() use($app) {
    $app->format('*', function() {
        return $app->response(401, 'Unauthorized');
    });
});

The problem with doing it in-line with the get method - and why Bullet doesn't return that by default - is because that will always be executed, no matter which format is matched. If you're doing something simple like just creating a response object it's no big deal, but I don't want to give people the idea that they can do other things there and it's okay.

vlucas commented 9 years ago

Default handling is now allowed since 6a169d3638570398b02724a32905adbf7b0119ad - If the Accept header is empty, the first format block found will be executed and returned. So if you want JSON, just make sure your JSON format is first. Does this solve your problem?