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

Reverse url #12

Closed
saml opened this issue Mar 31, 2015 · 12 comments
Closed

Reverse url #12

saml opened this issue Mar 31, 2015 · 12 comments
Assignees

Comments

@saml
Copy link

saml commented Mar 31, 2015

Needs a function that behaves as follows:

e.Get("/users/:id", getUser)
e.URL(getUser, "123")
// => "/users/123"
@zbindenren
Copy link

+1

@patrickdappollonio
Copy link

+1! This, while it looks like nothing, could make a huge difference maintaining big websites, and you can be confident that any route change you won't need to go through your entire code base to see what to change...

@fundon
Copy link

fundon commented Apr 1, 2015

+1 url path helper

@emilgpa
Copy link

emilgpa commented Apr 7, 2015

+1

@vishr
Copy link
Member

vishr commented Apr 7, 2015

I would like to know some practical example of this case. Please point me to some frameworks API supporting it.

@saml
Copy link
Author

saml commented Apr 7, 2015

One practical use case is when I want to write a RESTful API with hyperlinks.
For example, using HAL , I would want resource representation to include various links to other states client can go from here.

Of course I can write methods for calculating urls for various resources. But it involves duplicate work. If I change route, I need to change my relevant UrlFor method as well.

Some routing frameworks that support reverse url:

Play one is interesting cause routes are defined in DSL and generates reverse route functions during compilation.

If routes are specified using URI Template, it's known to be reversible: https://github.com/jtacoma/uritemplates (see Expand).

@patrickdappollonio
Copy link

Here's another framework who has this functionality: http://laravel.com/docs/5.0/routing#named-routes

@vanng822
Copy link

vanng822 commented Apr 7, 2015

It is convenient to bind this kind of method to request/router but there is a drawback when you have small number applications/services which need those urls. We had some extra implement/workaround to make thing work. I tried to fix it just providing a route manager https://github.com/vanng822/r2router/blob/master/example/routemanager.go
Maybe something?

@vishr vishr self-assigned this Apr 19, 2015
@vishr vishr closed this as completed in 8d3cd84 Apr 22, 2015
@vishr
Copy link
Member

vishr commented Apr 22, 2015

@saml, @patrickdappollonio, @fundon: Let me know how it looks. Further, as I have a map of handler and url, do you think an API to return it will be helpful?

https://github.com/labstack/echo/blob/master/echo_test.go#L237

@newoga
Copy link

newoga commented Apr 24, 2015

@vishr, Just submitted a pull request with a couple more tests. It seems like this has some issues when the handlers are paired with a group. Was the API meant to work this way?

@newoga
Copy link

newoga commented Apr 24, 2015

Also, a couple of other suggestions...

  1. Maybe rather than the URI() method accepting a ...string, how about it accepts ...interface{}

This way we can pass any type of value and determine how it should become a string. For example, we should be able to determine if the interface that was passes implements the Stringer interface. That way if you pass a UUID object to to the reverse routing method, it could still work.

  1. Also, It might be nice to support sending a map to the reverse route method, such as...
e.Get("/users/:id/:files:/fid", getFile)
e.URL(getUser, map[string]interface{}{
  "id": "1", // string works
  "fid": 2, // int works
  "other_id": guid, // as long as it implements `String()` it would work
})

@newoga
Copy link

newoga commented Apr 24, 2015

Okay, I closed my original pull request and created a new one #37, this one actually fixes the issue when you call the URI() method on the right instance of *Echo.

That being said, I think it would be useful to maintain some kind of link between instances of *Echo and child *Echo when created by calling Group(). Not quite sure what the right API would be for this, but it would be nice if I could call the root *Echo.URI() and it would know how to create the URI for all handler on itself and its child *Echo.

To test this, we would have to add back the two checks in the TestEchoURL method:

    e := New()
    getGroups := func(*Context) {}
    getGroup := func(*Context) {}

    eg := e.Group("/groups")
        eg.Get("", getGroups)
    eg.Get("/:id", getGroup)

    // These two tests would currently fail
    if e.URI(getGroups) != "/groups" {
        t.Error("uri should be /groups")
    }
    if e.URI(getGroup, "1") != "/groups/1" {
        t.Error("uri should be /groups/1")
    }

   // These two tests currently pass
    if eg.URI(getGroups) != "/groups" {
        t.Error("uri should be /groups")
    }
    if eg.URI(getGroup, "1") != "/groups/1" {
        t.Error("uri should be /groups/1")
    }

In my opinion, ideally we can have it setup so all 4 pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants