Групповая маршрутизация Go 1.22 net/http

Я создаю API и хотел бы разделить конечные точки по функциям, поскольку увидел, что пакет net/http получил обновление, поэтому хотел попробовать его использовать.

Конечная точка /v1/user доставляет мне проблемы и не возвращает ожидаемые данные. Вот некоторые curl, которые могут помочь:

$ curl -X 'GET' 'http://localhost:5000/v1/user/john'      
GET /v1/user/{username}

$ curl -X 'GET' 'http://localhost:5000/v1/user/'
GET /v1/user

$ curl -X 'GET' 'http://localhost:5000/v1/user'
<a href = "/user/">Moved Permanently</a>.

Вот мой текущий код (я удалил лишние конечные точки):

// will be moved of the user.go file
userRouter := http.NewServeMux()
userRouter.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("GET /v1/user"))
})
userRouter.HandleFunc("GET /{username}", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("GET /v1/user/{username}"))
})

// will remain inside api.go
v1 := http.NewServeMux()
v1.Handle("/user/", http.StripPrefix("/user", userRouter))

main := http.NewServeMux()
main.Handle("/v1/", http.StripPrefix("/v1", v1))

server := &http.Server{ Addr: "localhost:5000", Handler: main }
server.ListenAndServe()

Что я пробовал:

  • Я попытался изменить путь конечной точки с "GET /" на "GET" или на "", но, очевидно, синтаксис неправильный.

  • Я попытался изменить путь обработчика userRouter с "/user/" на "/user", это приведет к тому, что все конечные точки перестанут работать.

$ curl -X 'GET' 'http://localhost:5000/v1/user/john'
404 page not found

$ curl -X 'GET' 'http://localhost:5000/v1/user/'    
404 page not found

$ curl -X 'GET' 'http://localhost:5000/v1/user'
<a href = "/">Moved Permanently</a>.
  • тогда как все еще с изменениями, но с удалением http.StripPrefix к маршрутизатору userRounter и добавлением /user к конечным точкам; единственная работающая конечная точка — это /v1/user. Код:
userRouter := http.NewServeMux()
userRouter.HandleFunc("GET /user", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("GET /v1/user"))
})
userRouter.HandleFunc("GET /user/{username}", func(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("GET /v1/user/{username}"))
})

v1 := http.NewServeMux()
v1.Handle("/user", userRouter)

main := http.NewServeMux()
main.Handle("/v1/", http.StripPrefix("/v1", v1))

server := &http.Server{ Addr: "localhost:5000", Handler: main }
server.ListenAndServe()

Запросы:

$ curl -X 'GET' 'http://localhost:5000/v1/user/john'
404 page not found

$ curl -X 'GET' 'http://localhost:5000/v1/user/'    
404 page not found

$ curl -X 'GET' 'http://localhost:5000/v1/user'     
GET /v1/user

Обрабатывайте /user и /user/, как описано в pkg.go.dev/net/http#hdr-Trailing_slash_redirection

Peter 24.04.2024 10:10

Также рассмотрите возможность использования io.WriteString(w, "foo") вместо w.Write([]byte("foo")).

jub0bs 24.04.2024 10:21
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
1
2
968
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

проблема вот в чем v1.Handle("/user", userRouter) ты забыл добавить /

package main

import (
    "net/http"
)

func main() {
    userRouter := http.NewServeMux()
    userRouter.HandleFunc("GET /user", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("GET /v1/user"))
    })
    userRouter.HandleFunc("GET /user/{username}", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("GET /v1/user/{username}"))
    })

    v1 := http.NewServeMux()
    v1.Handle("/user/", userRouter)
    v1.Handle("/user", userRouter)
    main := http.NewServeMux()
    main.Handle("/v1/", http.StripPrefix("/v1", v1))

    server := &http.Server{Addr: "localhost:5000", Handler: main}
    server.ListenAndServe()
}

Я бы порекомендовал вам написать простой код маршрутизации, подобный этому

package main

import (
    "net/http"
)

func main() {

    v1 := http.NewServeMux()
    v1.HandleFunc("/v1/user", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("GET /v1/user"))
    })

    v1.HandleFunc("GET /v1/user/{username}", func(w http.ResponseWriter, r *http.Request) {
        username := r.PathValue("username")
        w.Write([]byte("GET /v1/user/" + username))
    })


    server := &http.Server{Addr: "localhost:5000", Handler: v1}
    server.ListenAndServe()
}

Другие вопросы по теме