Do I need to use methods=['GET', 'POST'] in #app.route()? - python

My Forms send the age parameter via GET, and it worked with just this:
#app.route("/foo")
def foo():
age = request.args['age']
I did not bother with
#app.route('/foo', methods=['GET', 'POST'])
Does it matter?

It does not matter, in the sense that it will work. However usually, you would like to have several functions doing different things like. POST to /foo, means that you add an element, GET to /foo means that you retrieve the element(s) and DELETE to /foo means that you delete an element.

If you don't specify a methods argument to app.route(), then the default is to only accept GET and HEAD requests (*).
You only need to explicitly set methods if you need to accept other HTTP methods, such as POST, otherwise Flask will respond with a 405 Method Not Allowed HTTP response code when a client uses a HTTP method you didn't list, and your route function is simply not called.
So if your route should handle both GET and POST requests, but you forgot to add methods=['GET', 'POST'] to #route(), then you have a bug as POST requests result in a 405 response instead of your route handling the request.
In your case, however, you should not use methods=['GET', 'POST'], and instead let clients that try to use POST anyway know your route doesn't handle that method. Better to be explicit about the error than let it silently pass.
(*) HEAD is added whenever you use register a route that handles GET, and in case of a HEAD request, your route is called and only the headers are then served to the client. Flask automatically handles OPTIONS for you, the route is not called in that case.

As always, the answer is: it depends.
If you don't provide "methods" arguments, then Flask assumes the HTTP method is GET (and also accepts HEAD). So long as that assumption is valid, your code will work just fine.
If, however, your web page is communicated as a POST method (or DELETE, etc.), Flask will fail and complain that the POST (or DELETE, etc.) request is not allowed.
Think of this requirement as a redundancy check. Flask could have been written to adapt to whatever method is used in the HTTP request. Instead, Flask insists that you specify the method as a signal that the form of communication is intentional. This requirement makes the Flask implementation a little simpler at the cost of imposing the responsibility of coordinating the client-server interface on the programmer.

Related

what does endpoint mean in flask-restful

I defined some resource called WorkerAPI using flask-restful and the plan is to process POST request from /api/workers/new and GET request from /api/workers/. When using the following code
api.add_resource(WorkerAPI, '/api/workers/new')
api.add_resource(WorkerAPI, '/api/workers/')
I get errors:
AssertionError: View function mapping is overwriting an existing endpoint function: workerapi
Then I tried to use the following, which seems to work, although I don't know why it works.
api.add_resource(WorkerAPI, '/api/workers/new', endpoint='/workers/new')
api.add_resource(WorkerAPI, '/api/workers/', endpoint='/workers/')
It looks like redundant information to me though. It seems the site works as long as the two endpoints are defined as different strings. What does endpoint mean here?
The thing is that the add_resource function registers the routes with the framework using the given endpoint. If an endpoint isn't given then Flask-RESTful generates one for you from the class name.
Your case is WorkerAPI, the endpoint will beworkerapi for these two methods, better make endpoint explicit and avoid to have conflicting endpoint names registered.
For what's endpoint, you can refer to this answer for more details.
'endpoint' is actually an identifier that is used in determining what logical unit of your code should handle a specific request.
So, an URL path is mapped to an endpoint and then an endpoint is mapped to a view function in your flask app.
In your case, when you are explicitly defining your endpoints for your resources, it helps the flask app internally to map it efficiently to a list of routes, while when your are not explicitly defining it, flask takes some default value, as explained by #Tiny.D, in the above answer.

Simple way to detect browser or script

Complexities aside, what is the simplest quirty-and-dirty way to detect in a request whether that request was issues by a CLI program, such as curl, or whether it was by a browser? Here is what I'm trying to figure out:
def view(request):
if request.is_from_browser:
return HTML_TEMPLATE
else:
return JSON
Request.is_ajax() checks if the HTTP_X_REQUESTED_WITH header equals XMLHttpRequest. This is becoming an "industry standard" among web frameworks/libraries to separate Ajax calls from normal requests. But it depends on cooperation from the client side to actually set the header. There's no 100 % foolproof way of detecting browser, client, Ajax etc without this cooperation.
Btw, why do you need to know what's calling?
Somthing in the HTTP request headers, I'd first try using the Accept header. with the accept header the client can specify what sort of content it wants.this puts the responsibily on the client.

HTTP METHOD categorization cancel vs. delete

In an API, what HTTP METHOD should be used for a cancel operation.
I imagine this wouldn't be a DELETE request, because the resource is not being disposed of. In which case, should it be a POST or a PUT ? Here is some documentation, but I still am not clear on the distinction from this: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
This isn't a DELETE. Cancelling an operation is a state change and a state change means an update.
I would personally use a PUT because you normally know the URI of the resource you are updating.
Also see this post for more details: PUT vs POST in REST.

Get Pyramid View callable by it's path (request context)

I am making an app that would translate websocket messages to AJAX requests to the server. Mainly the decision is based on the fact that Pyramid already has a good URL dispatch system and it would be stupid not to use it.
The question is if there is an easy way to dispatch a URL in Pyramid (possibly an instanced Request object) to it's according view callable and get the view callable? Or at least get the output of the view callable related to the request?
I have tried the script from "prequest.py" which basically emulates a whole HTTP client and gives you the response (I have still not managed to get it work, but a look through the sources makes sense anyway) and I wouldn't like to do it that way.
You can reuse the code from the pview command to turn a path into a view reference:
from pyramid.scripts.pviews import PViewsCommand
pvcomm = PViewsCommand([])
view = pvcomm._find_view(path, request.registry)
The actual code to do this is a little involved, but the PViewsCommand does it all for us already.
I have managed to do it using Router.invoke_subrequest in the latest version of Pyramid (1.4a1).
This enables all the features related to routing. URL dispatch, parameter passing, tweens.
You can read about it here: http://docs.pylonsproject.org/projects/pyramid/en/latest/api/request.html#pyramid.request.Request.invoke_subrequest

Get the request uri outside of a RequestHandler in Google App Engine (Python)

So, within a webapp.RequestHandler subclass I would use self.request.uri to get the request URI. But, I can't access this outside of a RequestHandler and so no go. Any ideas?
I'm running Python and I'm new at it as well as GAE.
You should generally be doing everything within some sort of RequestHandler or the equivalent in your non-WebApp framework. However, if you really insist on being stuck in the early 1990s and writing plain CGI scripts, the environment variables SERVER_NAME and PATH_INFO may be what you want; see a CGI reference for more info.
Since using request outside code handling it is meaningless I assume you'd like to access it from some method called by handler without passing request to it. Your choices are:
Refactor code so that request is passed to it.
When the former is not possible use a hack by defining a global threading.local(), storing request somewhere in request handler and access it in your method.

Categories

Resources