I am writing an app in which users will be able to store information that they can specify a REST interface for. IE, store a list of products at /<username>/rest/products. Since the URLs are obviously not known before hand, I was trying to think of the best way to implement dynamic URL creation in Flask. The first way I thought of would be to write a catch-all rule, and route the URL from there. But then I am basically duplicating URL routing capabilities when Flask already has them built-in. So, I was wondering if it would be a bad idea to use .add_url_rule() (docs here, scroll down a bit) to attach them directly to the app. Is there a specific reason this shouldn't be done?
Every time you execute add_url_rule() the internal routing remaps the URL map. This is neither threadsafe nor fast. I right now don't understand why you need user specific URL rules to be honest. It kinda sounds like you actually want user specific applications mounted?
Maybe this is helpful: http://flask.pocoo.org/docs/patterns/appdispatch/
I have had similar requirement for my application where each endpoint /<SOMEID>/rest/other for given SOMEID should be bounded to a different function. One way to achieve this is keeping a lookup dictionary where values are the function that handle the specific SOMEID. For example take a look at this snippet:
func_look_up_dict = {...}
#app.route('<SOMEID>/rest/other', methods=['GET'])
def multiple_func_router_endpoint(SOMEID):
if SOMEID in func_look_up_dict.keys():
return jsonify({'result' = func_look_up_dict[SOMEID]()}), 200
else:
return jsonify({'result'='unknown', 'reason'='invalid id in url'}), 404
so for this care you don't really need to "dynamically" add url rules, but rather use a url rule with parameter and handle the various cases withing a single function. Another thing to consider is to really think about the use case of such URL endpoint. If <username> is a parameter that needs to be passed in, why not to use a url rule such as /rest/product/<username> or pass it in as an argument in the GET request?
Hope that helps.
Related
WHAT: I have a Flask server and I would like to build a route and pass it an undetermined number of parameters via a GET method.
WHY: I would like to give the user the ability to pick several dates from a date picker, and give this list to the server which would make an SQL request to my database to retrieve data corresponding to those dates selected by the user. There would be hundreds of files and I would also limit the number of requests/responses made for performance as much as possible.
I have little experience with Flask but enough to handle routes like:
#app.route('/photos/year=<int:year>&month=<string:month>', methods=['GET'])
or even :
#app.route('/photos/<year>.<month>', methods=['GET'])
I have 3 cases :
The user has the ability to choose an interval of dates, in which case I would use a route like '/photos/< dateFrom> _ to _< dateTo>' (without spaces) ;
or a single date, in which case I would use a route like '/photos/< date >'
or multiple dates non-necessarily contiguous, and I don't know how to handle it, but what I would do would look like something like this : '/photos/< date1>.< date2>?.< date3>?...'
('?': representing an optional parameter ; '...': representing an undetermined number of parameters, just like in programming language (actually this would be enough : '/photos/< date>...' if a syntax like '...' exists).
I've been looking for answers but couldn't find something. The only thing that may be interesting is passing a JSON object, but yet I don't know how to deal with this, I'm going to look to it until I get an answer. I will also have a look to Flask-RESTful extension in case it helps.
Any help would be appreciated.
I don't think there is a need for separate routes for three use cases. You might want to have a single GET route and receive dates as url params.
In this case your flask route will become:
#app.route('/photos', methods=['GET'])
you can now pass any key value pair in url as
/photos?date1=1&date2=2
you can access these params using
from flask import request
date1 = request.args.get('date1')
date2 = request.args.get('date2')
If you want a list of date just send them using same key in the URL and use
request.args.getlist(<paramname>)
However since in your case the keys that will come as parameters may vary from request to request, be careful to check if the key you are trying to use exist in the request that came. I recommend you to go through documentation of request object for more details.
However as a general practice if your parameters are more complex you can consider using JSON objects as payload instead of URL params.
I've looked around for a little while now and can't seem to find anything that even touches on the differences. As the title states, I'm trying to find out what difference getting your data via url path parameters like /content/7 then using regex in your urls.py, and getting them from query params like /content?num=7 using request.GET.get() actually makes.
What are the pros and cons of each, and are there any scenarios where one would clearly be a better choice than the other?
Also, from what I can tell, the (Django's) preferred method seems to be using url path params with regex. Is there any reason for this, other than potentially cleaner URLs? Any additional information pertinent to the topic is welcome.
This would depend on what architectural pattern you would like to adhere to. For example, according to the REST architectural pattern (which we can argue is the most common), you want do design URLs such that without query params, they point to "resources" which roughly correspond to nouns in your application and then HTTP verbs correspond to actions you can perform on that resource.
If, for instance, your application has users, you would want to design URLs like this:
GET /users/ # gets all users
POST /users/ # creates a new user
GET /users/<id>/ # gets a user with that id. Notice this url still points to a user resource
PUT /users/<id> # updates an existing user's information
DELETE /users/<id> # deletes a user
You could then use query params to filter a set of users at a resource. For example, to get users that are active, your URL would look something like
/users?active=true
So to summarize, query params vs. path params depends on your architectural preference.
A more detailed explanation of REST: http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
Roy Fielding's version if you want to get really academic: http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm
I am listening to a Flask URL of the form,
http://example.com:8080/v1/api?param1=value1¶m2=value2¶m3=value3¶m4=value4
Now, I want to achieve URL separation of the parameters in either of the below forms, (ForwardSlash)
http://example.com:8080/v1/api?param1=value1¶m2=value2/parameters?param3=value3¶m4=value4
OR (Semicolon)
http://example.com:8080/v1/api?param1=value1¶m2=value2;parameters?param3=value3¶m4=value4
I know these are not clean URLs and need to be avoided, but such is the usecase.
I am currently listening to the URL as,
#app.route('/v1/api', methods=['GET','POST'])
def api_call():
#....code for listening ...
How do I modify my code to get the URL separation as desired above?
I understand I am not following good principles of URL formation or other design principles, this is a use case requirement and am stuck on achieving this through Flask.
Instead of passing all the values as query params, can you use form-post to achieve this? You can pass an object using this method and will give you more flexibility on the type of data-structure that you want to achieve.
I have a simple GAE system that contains models for Account, Project and Transaction.
I am using Django to generate a web page that has a list of Projects in a table that belong to a given Account and I want to create a link to each project's details page. I am generating a link that converts the Project's key to string and includes that in the link to make it easy to lookup the Project object. This gives a link that looks like this:
My Project Name
Is it secure to create links like this? Is there a better way? It feels like a bad way to keep context.
The key string shows up in the linked page and is ugly. Is there a way to avoid showing it?
Thanks.
There is few examples, in GAE docs, that uses same approach, and also Key are using characters safe for including in URLs. So, probably, there is no problem.
BTW, I prefer to use numeric ID (obj_key.id()), when my model uses number as identifier, just because it's looks not so ugly.
Whether or not this is 'secure' depends on what you mean by that, and how you implement your app. Let's back off a bit and see exactly what's stored in a Key object. Take your key, go to shell.appspot.com, and enter the following:
db.Key(your_key)
this returns something like the following:
datastore_types.Key.from_path(u'TestKind', 1234, _app=u'shell')
As you can see, the key contains the App ID, the kind name, and the ID or name (along with the kind/id pairs of any parent entities - in this case, none). Nothing here you should be particularly concerned about concealing, so there shouldn't be any significant risk of information leakage here.
You mention as a concern that users could guess other URLs - that's certainly possible, since they could decode the key, modify the ID or name, and re-encode the key. If your security model relies on them not guessing other URLs, though, you might want to do one of a couple of things:
Reconsider your app's security model. You shouldn't rely on 'secret URLs' for any degree of real security if you can avoid it.
Use a key name, and set it to a long, random string that users will not be able to guess.
A final concern is what else users could modify. If you handle keys by passing them to db.get, the user could change the kind name, and cause you to fetch a different entity kind to that which you intended. If that entity kind happens to have similarly named fields, you might do things to the entity (such as revealing data from it) that you did not intend. You can avoid this by passing the key to YourModel.get instead, which will check the key is of the correct kind before fetching it.
All this said, though, a better approach is to pass the key ID or name around. You can extract this by calling .id() on the key object (for an ID - .name() if you're using key names), and you can reconstruct the original key with db.Key.from_path('kind_name', id) - or just fetch the entity directly with YourModel.get_by_id.
After doing some more research, I think I can now answer my own question. I wanted to know if using GAE keys or ids was inherently unsafe.
It is, in fact, unsafe without some additional code, since a user could modify URLs in the returned webpage or visit URL that they build manually. This would potentially let an authenticated user edit another user's data just by changing a key Id in a URL.
So for every resource that you allow access to, you need to ensure that the currently authenticated user has the right to be accessing it in the way they are attempting.
This involves writing extra queries for each operation, since it seems there is no built-in way to just say "Users only have access to objects that are owned by them".
I know this is an old post, but i want to clarify one thing. Sometimes you NEED to work with KEYs.
When you have an entity with a #Parent relationship, you cant get it by its ID, you need to use the whole KEY to get it back form the Datastore. In these cases you need to work with the KEY all the time if you want to retrieve your entity.
They aren't simply increasing; I only have 10 entries in my Datastore and I've already reached 7001.
As long as there is some form of protection so users can't simply guess them, there is no reason not to do it.
I'm almost afraid to post this question, there has to be an obvious answer I've overlooked, but here I go:
Context: I am creating a blog for educational purposes (want to learn python and web.py). I've decided that my blog have posts, so I've created a Post class. I've also decided that posts can be created, read, updated, or deleted (so CRUD). So in my Post class, I've created methods that respond to POST, GET, PUT, and DELETE HTTP methods). So far so good.
The current problem I'm having is a conceptual one, I know that sending a PUT HTTP message (with an edited Post) to, e.g., /post/52 should update post with id 52 with the body contents of the HTTP message.
What I do not know is how to conceptually correctly serve the (HTML) edit page.
Will doing it like this: /post/52/edit violate the idea of URI, as 'edit' is not a resource, but an action?
On the other side though, could it be considered a resource since all that URI will respond to is a GET method, that will only return an HTML page?
So my ultimate question is this: How do I serve an HTML page intended for user editing in a RESTful manner?
Another RESTful approach is to use the query string for modifiers: /post/52?edit=1
Also, don't get too hung up on the purity of the REST model. If your app doesn't fit neatly into the model, break the rules.
There is no such thing as a RESTful URI. It is false concept as URIs should be completely opaque to the client.
If it helps you to properly implement the HTTP uniform interface by avoiding verbs in your URIs then that's great, but don't feel constrained by what your URI looks like. It is very limiting to think of resource modeling as type of data modelling. A RESTful system usually needs to do way more than just CRUD operations, so you need to be creative about what resources you make available in your system.
If you create a URL and dereferencing it returns a 200 status code, then that URL refers to a resource. If you create another URL and it also returns a 200, then that is a difference resource.
That means:
http://example.org/customer/10.xml
http://example.org/customer/10.json
http://example.org/customer/10?format=xml
http://example.org/customer/10?format=json
are 4 different resources, and
http://example.org/customers
http://example.org/customers?closed=true
http://example.org/customers?page=2&pagelength=20
are also different resources.
Therefore to answer your question, if you do
GET /post/52/edit
and it returns a 200 status code and a representation, then it must be a resource.
Instead of calling it /post/52/edit, what if you called it /post/52/editor?
Now it is a resource. Dilemma averted.
I don't think /object/id/action is part of the REST specification.
Is your editor going to be a generic thing for all objects ? Then maybe your URL should look like
/editor/object/id
The action is an HTTP Verb ( GET,PUT,DELETE,POST ) and is supposed to be a part of the HTTP request and not part of the URL. For a better summary, check out this Wikipedia article on RESTful_web_services.