Search code examples
python-2.7flaskwerkzeug

Zero-length URL Segments


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.


Solution

  • 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',
    }