httprouter
httprouter is a high performance, scalable HTTP routing, we enumerated above net/http
deficiencies default route, are implemented httprouter, let's use an example, under httprouter understanding of this powerful HTTP routing.
installation:
go get -u github.com/julienschmidt/httprouter
In this example, first by httprouter.New()
generating a *Router
route pointer, then GET
the method is adapted to register a /
path Index
function, and finally *Router
passed as parameters to ListenAndServe
start the HTTP service to function.
package main import ( "log" "net/http" "github.com/julienschmidt/httprouter" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.Write([]byte("Index")) } func main() { router := httprouter.New() router.GET("/", Index) log.Fatal(http.ListenAndServe(":8080", router)) }
httprouter provide a quick way to use all of the HTTP Method, simply call the corresponding method can be.
func (r *Router) GET(path string, handle Handle) { r.Handle("GET", path, handle) } func (r *Router) HEAD(path string, handle Handle) { r.Handle("HEAD", path, handle) } func (r *Router) OPTIONS(path string, handle Handle) { r.Handle("OPTIONS", path, handle) } func (r *Router) POST(path string, handle Handle) { r.Handle("POST", path, handle) } func (r *Router) PUT(path string, handle Handle) { r.Handle("PUT", path, handle) } func (r *Router) PATCH(path string, handle Handle) { r.Handle("PATCH", path, handle) } func (r *Router) DELETE(path string, handle Handle) { r.Handle("DELETE", path, handle) }
Modern API, basically Restful API, supports named parameters httprouter provided, can easily help us develop Restful API. For example, we designed the API /user/flysnow
, so that a URL, you can view flysnow
the user's information, if you want to view other users, for example zhangsan
, we only need to access the API /user/zhangsan
can be.
URL includes two matching modes: / user /: name an exact match, / user / * name matches all modes.
package main import ( "github.com/julienschmidt/httprouter" "net/http" "log" "fmt" ) func main() { router:=httprouter.New() router.GET("/MainData", func (w http.ResponseWriter,r *http.Request,_ httprouter.Params) { w.Write([]byte("default get")) }) router.POST("/MainData",func (w http.ResponseWriter,r *http.Request,_ httprouter.Params) { w.Write([]byte("default post")) }) //精确匹配 router.GET("/user/name",func (w http.ResponseWriter,r *http.Request,p httprouter.Params) { w.Write([]byte("user name:"+p.ByName("name "))) // match all }) router.GET("/employee/*name",func (w http.ResponseWriter,r *http.Request,p httprouter.Params) { w.Write([]byte("employee name:"+p.ByName("name"))) }) http.ListenAndServe(":8081", router) }
Handler two different domain processing chain processing
package main import ( "fmt" "log" "net/http" "github.com/julienschmidt/httprouter" ) type HostMap map[string]http.Handler func (hs HostMap) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Println("222") //根据域名获取对应的Handler路由,然后调用处理(分发机制) if handler := hs[r.Host]; handler != nil { handler.ServeHTTP(w, r) } else { http.Error(w, "Forbidden", 403) } } func main() { userRouter := httprouter.New() userRouter.GET("/", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { w.Write([]byte("play")) }) dataRouter := httprouter.New() dataRouter.GET("/", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { w.Write([]byte("tool")) }) //分别用于处理不同的二级域名 hs := make(HostMap) hs["user.localhost:12345"] = userRouter hs["data.localhost:12345"] = dataRouter log.Fatal(http.ListenAndServe(":12345", hs)) }
httprouter provides a very convenient static files, you can put a directory hosted on the server for access.
router.ServeFiles("/static/*filepath",http.Dir("./"))
Use ServeFiles
should be noted that the first parameter path must be to /*filepath
, because we want to get the path information to be accessed.
func (r *Router) ServeFiles(path string, root http.FileSystem) { if len(path) < 10 || path[len(path)-10:] != "/*filepath" { panic("path must end with /*filepath in path '" + path + "'") } fileServer := http.FileServer(root) r.GET(path, func(w http.ResponseWriter, req *http.Request, ps Params) { req.URL.Path = ps.ByName("filepath") fileServer.ServeHTTP(w, req) }) }
example:
package main import ( "log" "net/http" "github.com/julienschmidt/httprouter" ) func main() { router := httprouter.New() //访问静态文件 router.ServeFiles("/static/*filepath", http.Dir("./files")) log.Fatal(http.ListenAndServe(":8080", router)) }
httprouter exception caught, httprouter allow a user, is provided PanicHandler
for processing the HTTP request panic occurred.
package main import ( "fmt" "log" "net/http" "github.com/julienschmidt/httprouter" ) func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { panic("error") } func main() { router := httprouter.New() router.GET("/", Index) //捕获异常 router.PanicHandler = func(w http.ResponseWriter, r *http.Request, v interface{}) { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "error:%s", v) } log.Fatal(http.ListenAndServe(":8080", router)) }
httprouter there are many small useful features, such as processing of 404, set by us Router.NotFound
to achieve, we take a look at Router
this array structure, you can find more useful features.
Router {struct type // by redirecting whether, from a given path slash RedirectTrailingSlash BOOL // whether by redirecting automatically repair path, such as a double slash, such as automatic repair single slash RedirectFixedPath BOOL // detect whether the current request the method is allowed HandleMethodNotAllowed BOOL // whether custom reply OPTION request HandleOPTIONS BOOL // 404 default processing NotFound http.Handler method // not allowed default processing MethodNotAllowed http.Handler // abnormal unified treatment PanicHandler func (http.ResponseWriter, http.Request *, interface {}) }