Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a helper to generate the URL for a resource #1264

Open
kgriffs opened this issue May 12, 2018 · 5 comments
Open

Add a helper to generate the URL for a resource #1264

kgriffs opened this issue May 12, 2018 · 5 comments
Labels
enhancement needs contributor Comment on this issue if you'd like to volunteer to work on this. Thanks!
Milestone

Comments

@kgriffs
Copy link
Member

kgriffs commented May 12, 2018

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

@kgriffs kgriffs added this to the Version 2.1 milestone May 12, 2018
@kgriffs kgriffs added needs contributor Comment on this issue if you'd like to volunteer to work on this. Thanks! and removed needs-decision proposal labels May 13, 2018
@kgriffs
Copy link
Member Author

kgriffs commented May 13, 2018

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

@kgriffs kgriffs modified the milestones: Version 2.1, Version 2.0 May 13, 2018
@nZac
Copy link

nZac commented May 14, 2018

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?

@timothyqiu
Copy link

Places I miss url_for:

  • For a 201 response, the url of another resource is needed to set the Location header.

    POST /gists
    Status: 201 Created
    Location: https://api.github.com/gists/aa5a315d61ae9438b18d
    
  • For a paged collection resource, the url of itself is needed to set the Link header or put them in the resulting response.

    GET /user/repos
    Status: 200 OK
    Link: <https://api.github.com/user/repos?page=3&per_page=100>; rel="next"
      <https://api.github.com/user/repos?page=50&per_page=100>; rel="last"
    

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

@kgriffs kgriffs modified the milestones: Version 2.0, Version 2.2 Nov 8, 2018
@goodmami
Copy link

goodmami commented Jul 12, 2019

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?

@kgriffs
Copy link
Member Author

kgriffs commented Jun 10, 2021

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.

@kgriffs kgriffs changed the title feat: Inter-resource delegation Add a helper to generate the URL for a resource Jun 10, 2021
@kgriffs kgriffs mentioned this issue Aug 3, 2021
14 tasks
@vytas7 vytas7 modified the milestones: Version 3.1, Version 3.2 Mar 14, 2022
@vytas7 vytas7 mentioned this issue May 22, 2022
9 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement needs contributor Comment on this issue if you'd like to volunteer to work on this. Thanks!
Projects
None yet
Development

No branches or pull requests

5 participants