golang httprouter


httprouter

httprouter 是一個高性能、可擴展的HTTP路由,上面我們列舉的net/http默認路由的不足,都被httprouter 實現,我們先用一個例子,認識下 httprouter 這個強大的 HTTP 路由。

 

安裝:

go get -u github.com/julienschmidt/httprouter

在這個例子中,首先通過httprouter.New()生成了一個*Router路由指針,然后使用GET方法注冊一個適配/路徑的Index函數,最后*Router作為參數傳給ListenAndServe函數啟動HTTP服務即可。

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 為所有的HTTP Method 提供了快捷的使用方式,只需要調用對應的方法即可。

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)
}

現代的API,基本上都是Restful API,httprouter提供的命名參數的支持,可以很方便的幫助我們開發Restful API。比如我們設計的API/user/flysnow,這這樣一個URL,可以查看flysnow這個用戶的信息,如果要查看其他用戶的,比如zhangsan,我們只需要訪問API/user/zhangsan即可。

URL包括兩種匹配模式:/user/:name精確匹配、/user/*name匹配所有的模式。

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")))
  })
  //匹配所有
  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處理鏈處理不同二級域名

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提供了很方便的靜態文件服務,可以把一個目錄托管在服務器上,以供訪問。

router.ServeFiles("/static/*filepath",http.Dir("./"))

使用ServeFiles需要注意的是,第一個參數路徑,必須要以/*filepath,因為要獲取我們要訪問的路徑信息。

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)
	})
}

例子:

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 異常捕獲,httprouter允許使用者,設置PanicHandler用於處理HTTP請求中發生的panic。

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還有不少有用的小功能,比如對404進行處理,我們通過設置Router.NotFound來實現,我們看看Router這個結構體的配置,可以發現更多有用的功能。

type Router struct {
    //是否通過重定向,給路徑自定加斜杠
	RedirectTrailingSlash bool
    //是否通過重定向,自動修復路徑,比如雙斜杠等自動修復為單斜杠
	RedirectFixedPath bool
    //是否檢測當前請求的方法被允許
	HandleMethodNotAllowed bool
	//是否自定答復OPTION請求
	HandleOPTIONS bool
    //404默認處理
	NotFound http.Handler
    //不被允許的方法默認處理
	MethodNotAllowed http.Handler
    //異常統一處理
	PanicHandler func(http.ResponseWriter, *http.Request, interface{})
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM