Zero-length URL Segments - python-2.7

Using the latest versions of Flask and Flask-RESTful, I have some very basic routes defined as such:
def build_uri_rules(uri_map):
for cls, uri in uri_map.iteritems():
api.add_resource(cls, uri)
uris = {
SampleController: '/samples/<string:hash_or_id>',
SampleFamilyController: '/samples/<string:hash_or_id>/family',
}
build_uri_rules(uris)
This works for uris requested 'properly', but what if the /samples/ endpoint is hit without a parameter, or the sample*family endpoint is hit with an empty sample id? Currently, this results in a 404 error. This works well enough, but I believe the proper thing here would be to throw a 400 error, as they found a proper URL but their data is improperly structured. Is there a way that I can force this behavior?
As a side note:
Looking through the Werkzeug docs, I see that werkzeug.routing allows a minimum length for certain url parameters, but I also see that it's got a minimum of 1. Admittedly, I've not look for why this is the case, but would this be the right tree to bark up? or should I rather simply create a global 404 handler that checks for the length of the parameter and raise the proper error from there?
Thanks!
EDITED: For code correctness.

I would say that hitting /samples/ or /samples/family (or even /samples//family) should result in a 404 as there is nothing at that endpoint.
If, however, you want to do otherwise, the simplest way to handle it would be create a 404 handler for just /samples/ and /samples/family that returns a note with more information about what the consumers of your API are most likely doing wrong.
uris = {
Explanitory400Controller: '/samples/',
SampleController: '/samples/<string:hash_or_id>',
Explanitory400Controller: '/samples/family',
SampleFamilyController: '/samples/<string:hash_or_id>/family',
}

Related

Get page insights and post insights in the same request

Hello i am trying to get page level insights and post level insights in the same request but cant seem to get the syntax correct.
page id /published_posts?fields=permalink_url,created_time,message,shares,reactions.limit(0).summary(1),comments.limit(0).summary(1),insights.metric(post_reactions_by_type_total,post_impressions_unique,page_posts_impressions_organic)&since=yesterday
This is my request for now but i wanna add page insights like page_fans and page_fans_city.
How can i do that?
You are using the published_posts endpoint there already, you can not go back “up” to the page object from there. You need to rewrite the whole thing so that you use the page id itself as the basic endpoint, and then request everything else via the fields parameter. The trick is to get the syntax and nesting right …
/page-id?fields=insights.metric(page_fans,page_fans_city),published_posts{…}
should work, inside the {…} you then put all the original fields you requested from the published_posts endpoint before, so
/page-id?fields=insights.metric(page_fans,page_fans_city),published_posts{permalink_url,
created_time,…,insights.metric(post_reactions_by_type_total,post_impressions_unique,
page_posts_impressions_organic)}
And &since=yesterday then just goes at the end again, after all that.
To have the since limitation still apply on the post level, it apparently needs to be added on that “field” again, syntax similar to .metric():
?fields=…,published_posts.since(yesterday){…}

Postman - turn off matching algorithm

I'm trying to build a decent mock API using Postman, and I stumbled upon its Matching algorithm.
Is there a way to turn it off, so that, for example, when I target the wrong query params, or simply the wrong URL, it does return a 404?
Currently the response from
my/api/path/endpoint?myParam=Test
is returned even when I submit to
my/api/path/endp
Which I really don't want.
Currently, there is no way to turn off query param matching. If the query params do not match the algorithm falls back to match the path. The path matching is based on a fuzzy string matching algorithm which is why you are getting a response even though you were expecting a 404. One workaround for this is to save another example response for with a response code of 404 for my/api/path/endpoint and then send the x-mock-response-code header key with the value 404. This should return the example you have stored with the 404 status code.

Designing of a WebService API for paths between two points

I have a Web Service which returns details of path between given two input points if exists. The Web Service API is something like getPath(Point start,Point end). Now if the path doesn't exist between given start & end points, how should API behave among below options
Return a null object
Throw a PathNotFoundException
Always include a status code in the response along with path details. In this case return empty path and status code as appropriate error code like "PATH_NOT_FOUND" / "ERROR"
Any other option? Please suggest.
Please let me know your views
Thanks,
Harish
Suggestion: 1. return null or empty path.
Throwing exceptions across http is probably not the best idea and returning status codes is a way to workaround throwing exceptions. The lack of a path is not something that should occur as error at the client side.
I would reserve exceptions/status codes for wrong parameters, wrong number of parameters, some server-side problems like inaccessible database etc.
Suppose you are querying the database for a list of customers from NY. Would you throw an exception if the list is empty or just return an empty list? This sounds exactly like your scenario.

Django url patterns - how to get absolute url to the page?

i'm trying to get full path of the requested url in Django. I use a such url pattern:
('^', myawesomeview),
It works good for domain.com/hello, domain.com/hello/sdfsdfsd and even for domain.com/hello.php/sd""^some!bullshit.index.aspx (although, "^" is replaced with "%5E")
But when I try to use # in request (ex. http://127.0.0.1:8000/solid#url) it returns only "/sold". Is there any way to get the full path without ANY changes or replacements?
BTW, I'getting url with return HttpResponse(request.path)
Thanks in advance.
The part of URI separated by '#' sign is called a fragment identifier. Its sense is to be processed on client side only, and not to be passed to server. So if you really need this, you have to process it with JS, for example, and pass it as a usual parameter. Otherwise, this information will never be sent to Django.

REST Architecture - How the Url of a complex method would look like?

I have the following Url which returns me the list of resources:
http://example.com/resources/
I also implemented a method which returns a specific resource (in this case, the resource 142).
http://example.com/resources/142
I would like to add a method which is outside the typical HTTP method: List, Create, Retrieve, Replace, Update. What is the pattern to follow? In my specific case, I need to check the availability of resource. How would the Url look like (http://example.com/resources/checkavailability/142)?
I though about simply using the GET method and retrieve that information as part of the object returned. However, some of my colleagues argue that this would not be efficient (the data to transfer would be much bigger than just returning true/false).
Thanks for the help!
There is no need for a resource to check the availability of another resource, and there is no need for a GET request, a HEAD request should be enough, this is the same as a GET request but without transferring the body. You can then look at the return codes, and via those determine if the resource is available. This is assuming you have properly implemented return codes.
Restful over HTTP gives you uniform interface, you often don't need to encode the actions inside your URL
Regarding your mentioned /checkavailability using GET returning payload inefficiency is a valid reason, so use HEAD (it only gives you back the response headers).
request:
HEAD /resources/123
response status:
404 Not Found: equals to /checkavailability == false
200 OK: equals to /checkavailability == true
Other suggestions uniform interface replacements:
/resources/list : GET /resources
/resources/replace/123: PUT /resources/123
/resources/update/123: PUT /resources/123
/resources/create: POST /resources