最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Why Does My Go http.ServeMux Routing Return 404 for Versioned API Paths? - Stack Overflow

programmeradmin1浏览0评论

I'm experimenting with routing in Go and ran into an issue where my API always returns a 404 Not Found when I try to access an endpoint like:

https://localhost:8080/api/v1/users/login

Here’s my routing setup:

func SetupRoutes(cfg *handler.Config, version string) http.Handler {
    mux := http.NewServeMux()
    apiPath := "/api/v" + version + "/"

    versionedRoutes := map[string]http.Handler{
        "users/":    SetupUserRoutes(cfg),
        "workouts/": SetupWorkoutRoutes(cfg),
        "sessions/": SetupSessionRoutes(cfg),
        "admin/":    SetupAdminRoutes(cfg),
    }

    // Register each versioned route with the main mux
    for path, handler := range versionedRoutes {
        mux.Handle(apiPath+path, http.StripPrefix(apiPath+path, handler))
    }

    fmt.Printf("%+v\n", mux)
    return mux
}

And my user routes:

func SetupUserRoutes(cfg *handler.Config) http.Handler {
    mux := http.NewServeMux()

    userRoutes := map[string]http.HandlerFunc{
        "/register": cfg.RegisterUser,
        "/login":    cfg.LoginUser,
        "/logout":   cfg.LogoutUser,
        "/edit":     cfg.EditUser,
        "/revoke":   cfg.PostRevoke,
        "/refresh":  cfg.PostRefresh,
        "/":         cfg.ViewUser,
    }

    for path, handler := range userRoutes {
        mux.HandleFunc(path, handler)
    }

    return mux
}

Issue:

  • The API works when I serve it on port 8080, but it returns 404 Not Found when I try accessing it via the versioned API path (/api/v1/users/login).
  • I'm not sure if routing with http.StripPrefix in this way is correct.

Questions:

  1. Why is my API returning a 404 when using /api/v1/users/login?
  2. Is it possible to route like this using http.NewServeMux()?
  3. What is the correct way to structure these routes so that they work under /api/v1/?

Would appreciate any insights. Thanks!

I'm experimenting with routing in Go and ran into an issue where my API always returns a 404 Not Found when I try to access an endpoint like:

https://localhost:8080/api/v1/users/login

Here’s my routing setup:

func SetupRoutes(cfg *handler.Config, version string) http.Handler {
    mux := http.NewServeMux()
    apiPath := "/api/v" + version + "/"

    versionedRoutes := map[string]http.Handler{
        "users/":    SetupUserRoutes(cfg),
        "workouts/": SetupWorkoutRoutes(cfg),
        "sessions/": SetupSessionRoutes(cfg),
        "admin/":    SetupAdminRoutes(cfg),
    }

    // Register each versioned route with the main mux
    for path, handler := range versionedRoutes {
        mux.Handle(apiPath+path, http.StripPrefix(apiPath+path, handler))
    }

    fmt.Printf("%+v\n", mux)
    return mux
}

And my user routes:

func SetupUserRoutes(cfg *handler.Config) http.Handler {
    mux := http.NewServeMux()

    userRoutes := map[string]http.HandlerFunc{
        "/register": cfg.RegisterUser,
        "/login":    cfg.LoginUser,
        "/logout":   cfg.LogoutUser,
        "/edit":     cfg.EditUser,
        "/revoke":   cfg.PostRevoke,
        "/refresh":  cfg.PostRefresh,
        "/":         cfg.ViewUser,
    }

    for path, handler := range userRoutes {
        mux.HandleFunc(path, handler)
    }

    return mux
}

Issue:

  • The API works when I serve it on port 8080, but it returns 404 Not Found when I try accessing it via the versioned API path (/api/v1/users/login).
  • I'm not sure if routing with http.StripPrefix in this way is correct.

Questions:

  1. Why is my API returning a 404 when using /api/v1/users/login?
  2. Is it possible to route like this using http.NewServeMux()?
  3. What is the correct way to structure these routes so that they work under /api/v1/?

Would appreciate any insights. Thanks!

Share Improve this question edited Mar 22 at 8:43 har17bar 9021 gold badge9 silver badges24 bronze badges asked Mar 6 at 2:37 CheezecakeCheezecake 214 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

With this setup, the route parsing will to like this:

  1. mux receives /api/v1/users/login
  2. mux matches that to /api/v1/ to be handled by apiMux
  3. apiMux receives /api/v1/users/login
  4. apiMux doesn't find a match

What you'll want to do is change mux.Handle(apiPath, apiMux) to mux.Handle(apiPath, http.StripPrefix(apiPath, apiMux))

Then, the trace becomes something like this:

  1. mux receives POST /api/v1/users/login
  2. mux matches that to /api/v1/ to be handled by http.StripPrefix("/api/v1", apiMux)
  3. apiMux receives POST /users/login
  4. apiMux matches that to /users to be handled by http.StripPrefix("/users", userMux)
  5. userMux receives POST /login
  6. userMux matches that to POST /login to be handled by cfg.LoginUser

It was probably a bit difficult to see this. Had you reduced your code to the absolute minimum needed to pre-produce the issue, it would have been obvious right away that you have two "levels" of prefixing, but only strip the prefix once.

发布评论

评论列表(0)

  1. 暂无评论