【发布时间】:2019-05-09 18:10:36
【问题描述】:
我看到了一个article written by Mat Ryer,关于如何使用服务器类型和作为func(http.ResponseWriter, *http.Request) 包装器类型的http 处理程序
我认为这是构建 REST API 的一种更优雅的方式,但是我完全不知道如何让包装器正常运行。我要么在编译时收到不匹配的类型错误,要么在调用时收到 404。
这基本上是我目前学习的目的。
package main
import(
"log"
"io/ioutil"
"encoding/json"
"os"
"net/http"
"github.com/gorilla/mux"
)
type Config struct {
DebugLevel int `json:"debuglevel"`
ServerPort string `json:"serverport"`
}
func NewConfig() Config {
var didJsonLoad bool = true
jsonFile, err := os.Open("config.json")
if(err != nil){
log.Println(err)
panic(err)
recover()
didJsonLoad = false
}
defer jsonFile.Close()
jsonBytes, _ := ioutil.ReadAll(jsonFile)
config := Config{}
if(didJsonLoad){
err = json.Unmarshal(jsonBytes, &config)
if(err != nil){
log.Println(err)
panic(err)
recover()
}
}
return config
}
type Server struct {
Router *mux.Router
}
func NewServer(config *Config) *Server {
server := Server{
Router : mux.NewRouter(),
}
server.Routes()
return &server
}
func (s *Server) Start(config *Config) {
log.Println("Server started on port", config.ServerPort)
http.ListenAndServe(":"+config.ServerPort, s.Router)
}
func (s *Server) Routes(){
http.Handle("/sayhello", s.HandleSayHello(s.Router))
}
func (s *Server) HandleSayHello(h http.Handler) http.Handler {
log.Println("before")
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
w.Write([]byte("Hello."))
h.ServeHTTP(w, r)
})
}
func main() {
config := NewConfig()
server := NewServer(&config)
server.Start(&config)
}
因为现在是这样,我只会返回一个 404 调用 localhost:8091/sayhello。 (是的,这是我在配置文件中设置的端口。)
之前,由于我使用的是 Gorilla Mux,因此我将处理程序设置为:
func (s *Server) Routes(){
s.Router.HandleFunc("/sayhello", s.HandleSayHello)
}
这给了我这个错误,我完全被难住了。
cannot use s.HandleSayHello (type func(http.Handler) http.Handler) as type func(http.ResponseWriter, *http.Request) in argument to s.Router.HandleFunc
我在this SO post 的解决方案中看到我应该使用http.Handle 并传入路由器。
func (s *Server) Routes(){
http.Handle("/sayhello", s.HandleSayHello(s.Router))
}
但是现在我如何在设置路由时阻止实际功能执行?我的打印语句中的"before" 在服务器启动之前出现。我现在不认为这是一个问题,但是一旦我开始为我打算使用它的数据库查询编写更复杂的中间件,它可能就会出现。
Researching 这种技术further,我发现其他读数表明我需要定义middleware 或handler 类型。
我不完全理解这些示例中发生了什么,因为它们定义的类型似乎没有被使用。
This resource 显示处理程序的编写方式,但不显示路由的设置方式。
我确实发现 Gorilla Mux 有 built in wrappers 用于这些东西,但我很难理解 API。
他们展示的例子是这样的:
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Do stuff here
log.Println(r.RequestURI)
// Call the next handler, which can be another middleware in the chain, or the final handler.
next.ServeHTTP(w, r)
})
}
路由是这样定义的:
r := mux.NewRouter()
r.HandleFunc("/", handler)
r.Use(loggingMiddleware)
r.Use 不注册 url 路由的目的是什么?
handler 是如何使用的?
当我的代码这样写时,我没有编译错误,但我不明白我的函数应该如何写回“Hello”。我想我可能在错误的地方使用了w.Write。
【问题讨论】:
标签: rest http go wrapper gorilla