GoWeb——HttpRouter简介

HttpRouter

ServeMux的一个缺陷是:无法使用变量实现URL模式匹配。而HttpRouter则可以。

HttpRouter是一个高性能、可扩展的第三方HTTP路由包。HttpRouter包弥补了net/http包中默认路由不足的问题。
下面用一个例子认识一下HttpRouter这个强大的HTTP路由包。

打开命令行终端,输入如下命令即可完成HttpRouter安装:

go get -u github.com/julienschmidt/httprouter

HttpRouter的使用方法如下:

首先使用httprouter…New()函数生成了一个Router路由
对象,然后使用GET()方法注册一个适配/路径的Index函数,最后将
Router对象作为参数传给ListenAndServe()函数即可启动HTTP服务。

import (
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
)

/*
使用HttpRouter包
*/

func main() {
	router := httprouter.New()
	router.GET("/", Index)
	log.Fatal(http.ListenAndServe(":8080", router))
}

func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	w.Write([]byte("Index"))
}

HttpRouter包为常用的HTTP方法提供了快捷的使用方式:

func (r *Router) GET(path string, handle Handle) {
	r.Handle(http.MethodGet, path, handle)
}

func (r *Router) HEAD(path string, handle Handle) {
	r.Handle(http.MethodHead, path, handle)
}

func (r *Router) OPTIONS(path string, handle Handle) {
	r.Handle(http.MethodOptions, path, handle)
}

// POST is a shortcut for router.Handle(http.MethodPost, path, handle)
func (r *Router) POST(path string, handle Handle) {
	r.Handle(http.MethodPost, path, handle)
}

func (r *Router) PUT(path string, handle Handle) {
	r.Handle(http.MethodPut, path, handle)
}

func (r *Router) PATCH(path string, handle Handle) {
	r.Handle(http.MethodPatch, path, handle)
}

func (r *Router) DELETE(path string, handle Handle) {
	r.Handle(http.MethodDelete, path, handle)
}

HttpRouter包中对URL使用两种匹配模式:

  1. 形如/user/name的精确匹配
  2. 形如/user/*name的匹配所有的模式
import (
	"github.com/julienschmidt/httprouter"
	"net/http"
)

/*
httprouter的匹配模式
*/
func main() {
	router := httprouter.New()
	router.GET("/default", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
		w.Write([]byte("default get"))
	})
	router.POST("/default", 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.POST("/user/*name", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
		w.Write([]byte("user name:" + p.ByName("name")))
	})
	http.ListenAndServe(":8080", router)
}

Handler包可以处理不同的二级域名。它先根据域名获取对应的Handler路由,然后调用处理(分发机制)。

import (
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
)

func main() {
	userRouter := httprouter.New()
	userRouter.GET("/", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
		w.Write([]byte("sub1"))
	})

	dataRouter := httprouter.New()
	dataRouter.GET("/", func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
		w.Write([]byte("sub2"))
	})

	//分别处理不同的二级域名
	hs := make(HostMap)
	hs["sub1.localhost:8080"] = userRouter
	hs["sub2.localhost:8080"] = dataRouter

	log.Fatal(http.ListenAndServe(":8080", hs))
}

type HostMap map[string]http.Handler

func (hs HostMap) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//先根据域名获取对应的Handler路由,然后调用处理
	if handler := hs[r.Host]; handler != nil {
		handler.ServeHTTP(w, r)
	} else {
		http.Error(w, "Forbidden", 403)
	}
}

HttpRouter包提供了很方便的静态文件服务。如果要把一个目录托管在服务器上以供访问,则只需要调用ServeFiles()方法。该方法的定义如下:

func (r *Router)ServeFiles(path string,root http.FileSystem)

在使用ServeFiles()方法时需要注意:第1个参数路径必须是*/filepath形式,第2个参数为文件目录。示例代码如下。

import (
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
)

func main() {
	router := httprouter.New()
	//访问静态文件
	router.ServeFiles("/static/*filepath", http.Dir("./files"))
	log.Fatal(http.ListenAndServe(":8080", router))
}

HttpRouter包允许使用者设置PanicHandler,以处理在HTTP请求中发生的panic异常。Handler包通过PanicHandler处理异常的示例代码如下。

import (
	"fmt"
	"github.com/julienschmidt/httprouter"
	"log"
	"net/http"
)

func main() {
	router := httprouter.New()
	router.GET("/", Index1)

	//捕获异常
	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))
}

func Index1(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
	panic("error")
}

HttpRouter包的Router结构体还有其他配置,比如是否通过重定向、是否监测当前请求的方法被允许等配置。Router结构体里的代码如下:

type Router struct {
	//是否通过重定向给路径自动去掉斜杠(/)
	//例如:如果请求了/foo/,但路由只存在/foo
	//则对于GET请求,客户端被重定向到/foo,HTTP状态代码为301
	RedirectTrailingSlash bool

	//是否通过重定向自动修复路径,比如双斜杠(//)被自动修复为单斜杠(/)
	RedirectFixedPath bool

	//是否监测当前请求的方法被允许
	HandleMethodNotAllowed bool

	//是否自动答复OPTION请求
	HandleOPTIONS bool

	//404错误的默认处理
	NotFound http.Handler

	//不被允许的方法的默认处理
	MethodNotAllowed http.Handler

	//异常容易处理
	PanicHandler func(http.ResponseWriter, *http.Request, interface{})
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值