Falcon: Add a helper to generate the URL for a resource

Created on 12 May 2018  路  5Comments  路  Source: falconry/falcon

As a REST-focused framework, Falcon really should make it easier to generate a URL for a given resource. This will help encourage the use of hypermedia by lowering the barrier to entry.

Prior Art

enhancement needs contributor

Most helpful comment

Places I miss url_for:

Without something like url_for, I have to hard code the route or parse & unparse req.uri.

All 5 comments

(Please comment below re a design proposal if you are interested in taking this on, thanks!)

Much of the way that Flask.url_for is implemented in Werkzueg- specifically in the routing code.

The basic premise within that code is to utilize the Flask.url_map._rules_by_endpoint to grab the rule that is mapped to that endpoint and use that to build a URL with the appropriate values for the route. When reading through the compiled router I am not seeing anything obvious that indicates how we could use the same method. Does the compiled router keep a resource class -> url map anywhere?

I can understand that people do want it, but _why_ do people want it? Is generating a URL based on resource a required competency of an API framework? Flask has Jinjna2 bundled for generating HTML so url_for seems to make sense there, within Falcon I haven't seen a need for it yet. Any details on the use case could be helpful.

A reason I could be confused is that, "inter-resource delegation"/"to facilitate one resource calling into another" and url_for seem to be different use cases. When I think of inter-resource delegation, I think of some resource calling an HTTP (get/post/put/delete) method of a different resource without going through the entire web stack. Is that what is meant? If so, how does that relate to url_for?

Places I miss url_for:

Without something like url_for, I have to hard code the route or parse & unparse req.uri.

When I think of inter-resource delegation, I think of some resource calling an HTTP (get/post/put/delete) method of a different resource without going through the entire web stack.

I agree. Perhaps this issue could be renamed if it is about generating the URLs for resources?

Given how much weight Roy Fielding puts on link-driven APIs I'm surprised that a REST-focused framework like Falcon does not have a way to create a URL for a resource.

E.g, for some hypothetical API, if I query /products I would expect a list of product summaries including a link to each product's resource. I suppose Falcon expects users to format their own URLs (note: I'm new here; maybe there's something I'm missing), but it seems there's enough complexity that it's easy to get wrong. What if I have multiple routes to the same resource (e.g., /products and /products/{item})? What about escaping and encoding the URL so it is valid? Something like api.make_url(ProductResource, item_id) that returns /products/1234 or http://example.com/products/1234 would be very useful.

edit: here is essentially how I'm doing it now:

class ProductResource(object):
    def on_get(self, req, resp):
        urljoin = urllib.parse.urljoin
        quote = urllib.parse.quote
        data = [{'name': prod.name,
                 'url': urljoin(req.prefix, 'products/' + quote(prod.id))}
                for prod in self.products]
        resp.media = data
        resp.status = falcon.HTTP_OK

I'm not primarily a web-developer so I'm not sure how good that is. And what if req.prefix has a WSGI app part after the host? Maybe I should use '/products/' for this case?

Since #1228 speaks to delegating a response to another resource/route, I think it makes sense to rename this issue to focus solely on generating the hyperlink.

Was this page helpful?
0 / 5 - 0 ratings