Hello 👋
I’ve started learning Go a couple days ago. Currently, I’m building Rest APIs using net/http
package.
I have figured out most of the basic stuff, but struggling a bit with subrouting. When I add a subrouter using like this
var mux1 = http.NewServeMux()
mux1.HandleFunc(...) var mux2 = http.NewServeMux()
mux2.HandleFunc(...)
mux1.Handle("/", middleware.IsAuthenticated(mux2))
I’m trying to add a protected set of routes to a router using a middleware. But, the routes defined in the subrouter are not accessible without adding a trailing slash in the URL when making the request. eg:
My Code
// cmd/main/main.go
package main import ( "fmt" "net/http" "rest-api/internal/middleware" "rest-api/internal/routes" "rest-api/internal/utils"
) func main() { var middlewareStack = utils.CreateStack(middleware.LogRequest) var v1Router = http.NewServeMux() v1Router.Handle("/v1/", http.StripPrefix("/v1", routes.EchoRouter())) var usersRouter = routes.UsersRouter() v1Router.Handle("/users/", http.StripPrefix("/users", usersRouter)) var server = &http.Server{ Addr: ":8080", Handler: middlewareStack(v1Router), } fmt.Println("starting server on port 8080") server.ListenAndServe()
} // internal/routes/users.go
package routes import ( "encoding/json" "net/http" "rest-api/internal/middleware"
) type User struct { Name string Email string
} func UsersRouter() http.Handler { var usersMux = http.NewServeMux() usersMux.HandleFunc("GET /", getUsers) var protectedMux = http.NewServeMux() protectedMux.HandleFunc("POST /", createUser) usersMux.Handle("/", middleware.IsAuthenticated(protectedMux)) return usersMux
} func getUsers(res http.ResponseWriter, _ *http.Request) { res.Write([]byte("users list"))
} func createUser(res http.ResponseWriter, req *http.Request) { var newUser User var err = json.NewDecoder(req.Body).Decode(&newUser) if err != nil { res.WriteHeader(http.StatusBadRequest) res.Write([]byte(err.Error())) return } res.WriteHeader(http.StatusCreated) res.Write([]byte("new user created, name: " + newUser.Name + ", email: " + newUser.Email))
}
PS
I can achieve the desired behaviour by using the /users
prefix in the users.go
file instead of the main.go
file, but I was wondering if it can be done this way too 🤔
Thanks!