Coder Social home page Coder Social logo

Discussion: Top-Level Router API about muxy HOT 14 CLOSED

gorilla avatar gorilla commented on May 20, 2024
Discussion: Top-Level Router API

from muxy.

Comments (14)

moraes avatar moraes commented on May 20, 2024

It's ok to have both Handle(h http.Handler, m ...string) (notice that it's not Handler, to be consistent with http.ServeMux) and HandleFunc(h http.HandlerFunc, m ...string) methods. The convenience methods Get(), Post() keep accepting a HandlerFunc, and there's no need for equivalents that accept a Handler.

A Subrouter is a very lightweight route factory, while Router carries data and logic that go well beyond this. Making Subrouter() return *Router would mix this distinction and require Router to have a prefix and a router field itself (empty and nil for the main Router) and check if it is the main router in every method, and call the main router if not, and so on, while a Subrouter would not use any of the fields used by the main router. It would be a type trying to act as two types, and this sounds like a messy design.

So Subrouter should only have methods to create a Route and another Subrouter. I don't see it having more than 2 methods, ever.

Maybe Subrouter just needs a better name, because it's not really a router.

from muxy.

garyburd avatar garyburd commented on May 20, 2024

The http.HandlerFunc type should not be used as the handler function argument type. The documentation for http.HandlerFunc does not apply to the use of the type in this package. The HandlerFunc.ServeHTTP method is not needed here. Both of these issues can confuse newbies.

I suggest using the anonymous function type func(w http.ResponseWriter, r *http.Request) or declaring a named type in this package. I prefer the anonymous type because there's one less named type for the programmer to understand.

from muxy.

moraes avatar moraes commented on May 20, 2024

Interesting. I never even considered not using HandlerFunc, but thinking about it, the anonymous function way would suffice.

from muxy.

elithrar avatar elithrar commented on May 20, 2024

RE: the sub-router having only two methods - this might confuse users since you don't get access to any of the convenience methods on *Router - e.g. r.Route and makes a sub-router a much more limited router.

e.g.

s := r.Sub("/users")
s.Handle("/new", myHandler)      // matches "/users/new"
s2 := s.Sub("/{id}")
s2.Handle("/", myHandler)        // matches "/users/{id}/"
s2.Handle("/tickets", myHandler) // matches "/users/{id}/tickets"

... could instead be:

r := router.New()
r.Get("/", indexHandler)
s := router.New()
r.Handle("/users", s)  // tell the top-level router to pass any requests prefixed with "/users" to s.
s.Handle("/new", userHandler)      // matches "/users/new"
s.Get("/list", userList)    // matches "/users/list"

This is functionally similar to the way Goji (https://godoc.org/github.com/zenazn/goji/web#Mux) tackles sub-routers.

You can have packages initialize their own routers (e.g. JSON API, web, static) and then import them in your package main and plug them into your top-level router via r.Handle("/prefix", package.ExportedRouter).

from muxy.

moraes avatar moraes commented on May 20, 2024

In this case:

r := router.New()
r.Get("/", indexHandler)
s := router.New()
r.Handle("/users", s)
s.Handle("/new", userHandler)
s.Get("/list", userList) 

...when you call s.URL(name) would you get a URL with or without the /users prefix?

from muxy.

kisielk avatar kisielk commented on May 20, 2024

This may be just my opinion, but I think we could do without the convenience functions. It makes declarations less readable because there's more different kinds of functions, and s.Handle("/foo", h) and s.Get("/foo", h) are already basically redundant (unless I'm missing something...). It saves a very small amount of typing in exchange for a loss in readability and a bigger API.

from muxy.

kisielk avatar kisielk commented on May 20, 2024

Another thing to consider is to use option types like the CSRF package instead of strings, and then have the function be Handle(path string, options ...Option). The route declarations would then be r.Handle("/foo", muxy.Post) etc. However you could also pass other option constructors in to Handle.

from muxy.

moraes avatar moraes commented on May 20, 2024

@elithrar: The name Subrouter in this initial proposal is a bit misleading, because it is not doing any nested dispatch, nor it's merging routes from one router into another. It is just a convenience to register URL's that share a common prefix (a domain and/or path). It's dumb but kinda lovely.

To achieve what you want, we would need something different. For example, package1 defines a router:

r := mux.New()
r.Route("/bar").Handler(barHandler)

And package2 imports it and submounts it under a given prefix:

r := mux.New()
r.Mount("/foo", package1.r)

In the end, only package2's router would know how to build the URLs that are being served, though.

from muxy.

garyburd avatar garyburd commented on May 20, 2024

we could do without the convenience functions

Here's an example without the convenience functions:

r.Route("/foo").Handle(h, "GET")
r.Route("/bar").Handler(getBar, "GET").Handler(updateBar, "POST")

and the same example with the convenience functions:

r.Route("/foo").Get(h)
r.Route("/bar").Get(getBar).Post(updateBar)

from muxy.

moraes avatar moraes commented on May 20, 2024

The convenience functions are a delicate dilemma.

Sure, the API would be tidier without them, and they could be defined elsewhere through proxy types, but they make usage easier and prettier for common enough scenarios, and I think it has been proved that people like them.

from muxy.

elithrar avatar elithrar commented on May 20, 2024

I'm definitely +1 for the convenience functions. They make sense when you
have separate handlers for each method (e.g. GET vs. POST). There's
obviously a small API surface cost but I think enough routers in Go-land
provide similar methods to make the cost reasonable.

On Tue, Oct 27, 2015 at 7:40 AM rodrigo moraes [email protected]
wrote:

The convenience functions are a delicate dilemma.

Sure, the API would be tidier without them, and they could be defined
elsewhere through proxy types, but they make theusage easier and prettier
for common enough scenarios, and I think it has been proved that people
like them.


Reply to this email directly or view it on GitHub
#1 (comment).

from muxy.

AaronO avatar AaronO commented on May 20, 2024

@moraes I definitely think Router.Mount() would be really nice to have, I've written my thoughts down here: gorilla/mux#136

from muxy.

moraes avatar moraes commented on May 20, 2024

@AaronO, soon:

// Mount imports all routes from the given router into this one.
//
// Combined with Sub() and Name(), it is possible to submount routes using
// pattern and name prefixes:
//
//     r := New()
//     s := r.Sub("/admin").Name("admin:").Mount(admin.Router)

from muxy.

muir avatar muir commented on May 20, 2024

I have a use case where I want to combine routers. Some method to let me do that would simplify my code by 200+ lines.

With a way to combine routers, I could drop half of my documented features: http://godoc.org/github.com/BlueOwlOpenSource/endpoint

from muxy.

Related Issues (11)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.