-
-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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
Response format control through filter #2034
Comments
I don't think this is needed. Normally you would use the same response format for ALL actions of a controller (e.g. REST api). Sometimes the format could be conditional (e.g. format negotiation based on header info). In this case, your proposal doesn't work either. |
Usually i faced with situation that no, for example you have |
@qiangxue For example we have possibility to manage tags. Also we need action like list which used for jquery plugins to autosuggest tags. Can you show best practice then? As i understand you suggest to separate controllers into
Can you confirm about separation? |
@creocoder what is the list action used for? Do not really see why it is bad to set response format in one action that is different. |
@cebe I do not say its bad. |
@cebe And this is why this issue created. I just want to avoid code like |
I'm against it. |
@samdark Using it inside
Following this logic something like: if (Yii::$app->user->checkAccess('some')) {
...
} is too short and clean, but we have AccessFilter for it. So why not have filter for Responsible. Where is logic? |
I'm against this too. It's making simple thing complicated.
|
@qiangxue Ok, then lets remove Verb filter than? It too make things complicated. You can do imperative checks for verbs. This ticket about imperative VS declarative. I see no any complication here. |
Can you try to write plain PHP code without using verb filter? You will see it's not as trivial as this one-liner, and because of this, you want to use the verb filter to avoid lot of duplicated code. |
Against it too, no real profit, |
Ok, saw that another frameworks have declarative feature for control response type, but ok, convienced. |
could you post some links? |
@cebe Ofrouse for example Symfony 2 has both imperative and declarative ways. Read this for example: Declarative way is:
Format controlled via router configuration. Anyway another frameworks has similar or different approaches to set response type. The main thing they have declarative in addition to imperative way. We have only imperative way, which is enough for home grown blog, but smells like bad practice for other types of applications. |
Reopening this. Will check what we can do about it. It is not suiteable as an action filter imo but there need to be simple ways to configure this kind of behaviors. |
@creocoder The code you show here isn't exactly the declarative way of setting response type. It's actually similar to what you do with Yii URL rule:
|
@qiangxue I'm fine with any solution which will allow not write |
@qiangxue any docs on this feature or example?
I think that simple check of if isset |
@qiangxue I am for supporting this. Very important for APIs that expose JSON and XML, a common use-case. To clarify the problem here, I think we essentially want Symfony FOSRestBundle's format-agnostic controllers. Actions would be expected to set With this setup, it's possible to determine before the action is run whether the app can return the type requested by the client. That means we can HTTP 400/500 all over the place before hitting the database. (BIG WIN!) Seems like a great idea to me.
@creocoder This gets at how distasteful it is to (essentially) combine your API with your view server. It feels better to have one format (or one conditional) per controller because it is, and because that's exactly how our APIs work. Nice to know I'm not the only one who does it and cringes afterwards :) That said... does this belong in core? |
@danschmidt5189 we already have issues for web-api, check them. |
Any news on this one? i guess simple rule with |
@creocoder @Ragazzo I use a filter for content-negotiation. Is this what you're referring to? It checks request parameters to see if a format was requested. (Supports checking headers, query, and body.) Details are in the comments below. I could PR if there's interest. Example configuration: // Sets the application Response::$format
'format' => [
'class' => '\app\filters\FormatNegotiationFilter',
// List of supported actions
'actions' => ['*'],
// Formats supported by the configured actions
// Defaults to array_keys(Response::$formatters)
'supports' => ['json', 'xml', 'view'],
// If no requested format is supported
'unacceptableCallback' => function ($accepted, $supported) {
throw new NotAcceptableHttpException();
},
// Format negotiation rules (source => param)
// Source can be 'query', 'body', or 'header'. The param specifies the name
// of the parameter in the given source to be checked for a format.
//
// E.g.
// ~~~
// 'header' => 'X-Format' : $request->headers->get('X-Format')
// 'query' => 'format' : $request->query->get('format')
// 'body' => '_format' : $request->body->get('_format')
// ~~~
//
// Rules are checked in order. The first supported format is set as the
// response format. If a format is not specified, the response is not modified.
// If a format is specified but not supported, invokes the unacceptableCallback.
'negotiation' => [
'header' => 'X-Request-Format',
'query' => 'format',
],
], |
yeah, but this is too big for fw itself, so simple check in |
Same argument applies to |
@qiangxue @Ragazzo Have you heard of Rails'
Here's the official Responder documentation.
These are highly relevant to Issue #303 and very powerful for developers, allowing them to write a single controller per resource, including custom formats (e.g. versioned ones). Qiang's idea to replace the ModelSerializer with interfaces (e.g. toJson, toXml?) might fit well with this. |
@danschmidt5189 yes, but we are not going that way, we will have rest support in other way. however i dont see good solution now for this issue with your suggested methods, because we dont have good syntax like |
@Ragazzo No, but we have callbacks. What's the problem?
Essentially what I want is for a single action to be able to return multiple formats with as little code/pain as possible. In 95% of cases those formats are:
I'm not sure how that's possible in the current setup, and especially not if the REST controller/actions are different classes from ordinary controllers. |
yes, we have callbacks, but we loose readability and syntax, not sure about that. Anyway PR will be better to review, if you have time) |
@qiangxue this is realated to API implementation, can you check whether it got obsolete since API branch is merged? |
Let's keep it open. Current REST implementation is based on a controller method. Will think about abstracting this out as a class so that it can be used elsewhere. |
* 'master' of github.com:yiisoft/yii2: (79 commits) Refactored app bootstrap logic. Update authorization.md Fixes #3052: Fixed the issue that cache dependency data is not reused when `reusable` is set true start debug logging only if debug runs when bootstrap. Update finnish translation Add ODBC support to yii\db\Connection updated error handler and requirement checker links. fixed broken API links [skip ci] added more doc [skip ci] update class map. Fixes #2034: Added `ContentNegotiator` to support response format and language negotiation renamed attributes to attributeNames in model updated phpdoc Removed `Application::preload` in favor of `Application::bootstrap` Update module-debug.md Update model.md Fixes Update basics.md typo fix [skip ci] Added `HtmlResponseFormatter` and `JsonResponseFormatter` ...
Currently we have possiblity to do this job operativelly:
How about creating filter to avoid code like this? Something like:
Also since we have traits maybe its not needed to intruduce new class and just impove Response class to have possibility to work as filter. Not sure about this filter syntax yet. This is just idea about
operative
=>declarative
, since we haveoperative
=>declarative
possibilities for many other features.The text was updated successfully, but these errors were encountered: