Chi: Building urls from named routes

Created on 24 Jun 2017  路  5Comments  路  Source: go-chi/chi

It would be nice to have a function for building urls from named routes. Like described in #179. Gorilla Mux and Echo have it and it's really helpful.

Most helpful comment

if someone feels like doing some open source work, this could be an excellent ticket to work on and PR :) especially if you're solving it for yourself.

the recap, the proposed design for a url route builder:

func Routes() chi.Router {
  r := chi.NewRouter()
  r.Name("articles").Route("/articles", func(r chi.Router) {
    r.Get("/", ListArticles)
    r.Route("/{id}", func(r chi.Router) {
      r.Get("/", GetArticle)
    })
  })

  articleUrlExample := r.URLFor("articles", chi.Param{"id": "1"})
  fmt.Println(articleUrlExample) // prints: /articles/1

  return r
}

similar, but slightly different design..

func Routes() chi.Router {
  r := chi.NewRouter("articles")
  r.Route("/articles", func(r chi.Router) {
    r.Get("/", ListArticles)
    r.Route("/{id}", func(r chi.Router) {
      r.Get("/", GetArticle)
    })
  })

  articleUrlExample := r.URLFor("articles", chi.Param{"id": "1"})
  fmt.Println(articleUrlExample) // prints: /articles/1

  return r
}

All 5 comments

if someone feels like doing some open source work, this could be an excellent ticket to work on and PR :) especially if you're solving it for yourself.

the recap, the proposed design for a url route builder:

func Routes() chi.Router {
  r := chi.NewRouter()
  r.Name("articles").Route("/articles", func(r chi.Router) {
    r.Get("/", ListArticles)
    r.Route("/{id}", func(r chi.Router) {
      r.Get("/", GetArticle)
    })
  })

  articleUrlExample := r.URLFor("articles", chi.Param{"id": "1"})
  fmt.Println(articleUrlExample) // prints: /articles/1

  return r
}

similar, but slightly different design..

func Routes() chi.Router {
  r := chi.NewRouter("articles")
  r.Route("/articles", func(r chi.Router) {
    r.Get("/", ListArticles)
    r.Route("/{id}", func(r chi.Router) {
      r.Get("/", GetArticle)
    })
  })

  articleUrlExample := r.URLFor("articles", chi.Param{"id": "1"})
  fmt.Println(articleUrlExample) // prints: /articles/1

  return r
}

I would take over this work with pleasure. Unfortunately I'm a beginner and don't have enough experience to contribute to such an excellent project.

@pkieltyka I would like to take a shot at this. I do have a question about the design you propose, how would one go about reverse routing a router setup like this:

r.Name("articles").Route("/articles", func(r Router) {
    r.Get("/{a}foo{b}.*", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "foo") })
    r.Get("/{a}bar{b}.*", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "bar") })
})

By labeling just the router as "articles" it doesn't seem possible to just reverse to an url without specifying the actual endpoint? Also, how about the star (*)?

One could also think of a design that is more orthogonal, something in the spirit of github.com/alehano/reverse:

r.Name("articles").Route("/articles", func(r chi.Router) {
    r.Get("/{a}foo{b}.*", chi.Label("foo", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "foo") }))
    r.Get("/{a}bar{b}.*", chi.Label("bar", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "bar") }))
})

url1, err := r.URLFor("foo", chi.Params{"a": "a1", "b": "b1", "*": ".html"}
url2, err := r.URLFor("bar", chi.Params{"a": "a2", "b": "b2, "*": ".html"}


what's the status of this feature request?

@pkieltyka I would like to take a shot at this. I do have a question about the design you propose, how would one go about reverse routing a router setup like this:

r.Name("articles").Route("/articles", func(r Router) {
  r.Get("/{a}foo{b}.*", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "foo") })
  r.Get("/{a}bar{b}.*", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "bar") })
})

By labeling just the router as "articles" it doesn't seem possible to just reverse to an url without specifying the actual endpoint? Also, how about the star (*)?

One could also think of a design that is more orthogonal, something in the spirit of github.com/alehano/reverse:

r.Name("articles").Route("/articles", func(r chi.Router) {
  r.Get("/{a}foo{b}.*", chi.Label("foo", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "foo") }))
  r.Get("/{a}bar{b}.*", chi.Label("bar", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "bar") }))
})

url1, err := r.URLFor("foo", chi.Params{"a": "a1", "b": "b1", "*": ".html"}
url2, err := r.URLFor("bar", chi.Params{"a": "a2", "b": "b2, "*": ".html"}

For the star issue, i believe we could use a named parameter for that.

Just to note, I'm not going to be including this in core chi pkg, but someone could absolutely wrap a pkg on top and submit a request to publish under github.com/go-chi -- closing for now.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

makhov picture makhov  路  4Comments

nhooyr picture nhooyr  路  12Comments

rickb777 picture rickb777  路  12Comments

innovate-invent picture innovate-invent  路  11Comments

dannyvankooten picture dannyvankooten  路  5Comments