Comments (7)
@thing_bp.doc(responses={...})
seems to work well.
from flask-smorest.
The framework is based on a few opinionated choices. The way we use it, the view function can only return the "normal" response, the one for which the status code is specified in the @response
decorator.
Then there can be errors that interrupt the normal flow and generate an abort(another_status_code)
.
Indeed, you can document other responses using @doc
. It is precisely meant to add documentation that is not grabbed generated from the code. BTW, I'd like to make it easier to document error responses. I'm working on apispec to make this easier by allowing to declare reusable response components.
However, calling twice the @response
decorator is not supported. I'm pretty sure that would end up in a mess. I could add a check and raise an Exception
if someone attempts to do that.
So you can document the two error codes using @doc
, but how do you manage to actually return those error codes?
What is your use case? I suppose you're allowing PUT to create entities. Whether this is good practice is debated AFAIK. This is not something we do so we never tried to support it. We only use POST to create and PUT to update.
from flask-smorest.
The framework is based on a few opinionated choices. The way we use it, the view function can only return the "normal" response, the one for which the status code is specified in the
@response
decorator.
Yeah, it's been a pleasure to use it. This is just an edge case.
What I'm doing may not be considered strictly restful. My resource is a list of strings. Posting a list of strings once to /resource/<key>/
will create it, and subsequent calls will extend it. So it's not idempotent, hence the post instead of put.
So you can document the two error codes using
@doc
, but how do you manage to actually return those error codes?
It's actually success codes. I just decorate my view with bp.arguments
and bp.doc
(and not bp.response
), and return a normal flask response object from the view.
Indeed, you can document other responses using
@doc
. It is precisely meant to add documentation that is not grabbed generated from the code. BTW, I'd like to make it easier to document error responses. I'm working on apispec to make this easier by allowing to declare reusable response components.
Cool! I would have liked another decorator that takes the same args as response
(plus mimetype maybe), but just updates func._apidoc
, but maybe you have other plans in mind.
from flask-smorest.
What I'm doing may not be considered strictly restful. My resource is a list of strings. Posting a list of strings once to
/resource/<key>/
will create it, and subsequent calls will extend it. So it's not idempotent, hence the post instead of put.
Yes, this is not the common case. I won't comment on restfulness. What happens if you GET /resource/<key>/
before the first POST? 404 or empty list? In your case I'd be tempted to use PATCH and always return 200. But I'd still consider the whole thing smelly.
I have more or less similar case in an app and I use PATCH and return 204 because I don't return the result.
It's actually success codes.
I understand. What I meant is that I stick to the "only one possible successful code" approach and I'd like to add better means to document error codes.
I just decorate my view with bp.arguments and bp.doc (and not bp.response), and return a normal flask response object from the view.
OK, I get it. But then you're far off beaten paths. It works but not using @response
is not "supported". @response
does not only make the response, it also manages ETag (which I suppose you don't use on this resource, if at all), it adds pagination header, and it could do other stuff.
I would have liked another decorator that takes the same args as response (plus mimetype maybe), but just updates func._apidoc, but maybe you have other plans in mind.
It's not really the direction I'd like to take. I'd like to keep the doc inferred from the code as much as possible. When needed, use @doc
.
Regarding mimetype, I suppose you're referring to application/json
. Currently, it is hardcoded, and I'd like to make it a parameter, but it is a bit more complicated than I expected so I left it for later.
from flask-smorest.
What happens if you GET
/resource/<key>/
before the first POST?
It'll be a 404.
But I'd still consider the whole thing smelly.
Sure. I guess the alternative is post /resource/<key>/
to create it, and post/patch to /resource/<key>/append
to append to it. But let's not delve into this too deeply.
If you want to force users to have a single success response, then I'll accept it.
Regarding far off beaten paths and mimetypes, I have another view that responds with an image, where I'm also using not using bp.response
:
@bp.arguments(ArgsSchema, as_kwargs=True)
@bp.doc(
responses={
'200': {
'description': 'An image',
'content': {
'image/png': {
'schema': {
'type': 'string',
'format': 'binary',
}
}
}
}
}
)
def post(self, ...):
...
return send_file(img, mimetype='image/png')
I saw no other way to do it right now.
from flask-smorest.
If you want to force users to have a single success response, then I'll accept it.
I'm open to changes. It's a tradeoff between relevance of the use case and difficulty of the change. I don't see any easy way to change that.
Regarding the mime types, I was thinking of a way to globally replace the serializer, for instance to replace json with XML. This is easy, but making the doc consistent revealed more complicated than I thought.
I think you did the right thing about the image use case. Improving @response
to allow you to specify another mime type is only one part of the issue. You'd need to be able to replace the serializer (normally json), which we could allow at Blueprint
level, but I don't see how to do that at resource level. Overall, not using @response
for file UL/DL resources is probably the best way. In fact that's what we do. And we document the type manually using @doc
.
from flask-smorest.
Yeah, it seems to be very tricky.
Maybe you can check (in the response-wrapper) if the view returned a flask response, and if so, skip serialization. That could be a way for users to override the serializer at the resource level, atleast until there is another way to do it.
Just to clarify:
# Build response
if isinstance(resp, Response):
pass # do not serialize
elif mimetype == 'application/json': # default value
resp = jsonify(self._prepare_response_content(result_dump))
else:
raise SomeError
I guess you'd would have a mapping from mimetype to serialization function to make it proper.
from flask-smorest.
Related Issues (20)
- Inconsistent order of parameters when using rule.arguments from werkzeug inside FlaskPlugin HOT 10
- Pagination documentation example is incorrect HOT 3
- Are query based blueprint arguments after path arguments formally unsupported? HOT 5
- Support for mixed multipart forms HOT 5
- ImportError: cannot import name '_app_ctx_stack' from 'flask' HOT 4
- flask smorest import error HOT 1
- Swagger submitting incorrect format for Model-based form inputs HOT 4
- Proposal: Allow register_blueprint option to name the Blueprint outside of Flask HOT 1
- Werkzeug Security Issue
- How can i create pagination for method POST HOT 2
- Missing response header in OpenAPI documentation HOT 3
- How to show docs with nginx url prefix set? HOT 1
- Different `unknown` arguments behaviour locally vs on production HOT 2
- What's the best way to handle multiple routes per function? HOT 1
- Swagger isn't obeying required=True for IPv4 field HOT 6
- Schema validation of mandatory fields on a blueprint with a HTTP PATCH method containing only modified fields HOT 5
- TypeError: argument of type 'SchemaMeta' is not iterable when running flask --app '...' openapi print HOT 1
- Improving error handlers to satisfy both template and API server use cases HOT 6
- Endpoint isn't getting data from json_or_form arguments when using the Swagger UI HOT 8
- flask-smorest with subdomains and redoc HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from flask-smorest.