15 Star 88 Fork 24

konyshe / gogo

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
HTTPRouterHandler.go 5.74 KB
一键复制 编辑 原始数据 按行查看 历史
package gogo
import (
"fmt"
"net/http"
"strings"
"sync"
)
//固定URL前缀的钩子结构体
type preMuxEntry struct {
h preHttpProcFunc
pattern string
}
//固定URL结构体
type muxEntry struct {
h HttpProcFunc
pattern string
}
//含有":"的智能URL结构体
type imuxEntry struct {
h HttpProcFunc
pattern string
urlParams []string
}
// httpRouterHandler 保存注册函数的地方
type httpRouterHandler struct {
mu sync.RWMutex
//静态路径匹配
pm map[string]string
//特殊STATE匹配
sm map[int]muxEntry
//固定URL前缀特征匹配,钩子规则
//map["GET"/"POST"][pattern]muxEntry
pre_gm map[string]map[string]preMuxEntry
//固定特征的URL匹配
//map["GET"/"POST"][pattern]muxEntry
gm map[string]map[string]muxEntry
//含有":"的智能URL匹配
//map["GET"/"POST"][]imuxEntry
im map[string][]imuxEntry
//hosts bool // whether any patterns contain hostnames
}
// ServeHTTP 官方HTTP触发入口
func (mux *httpRouterHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
pctx := &HTTPContext{w: w, r: r}
//固定URL前缀特征匹配,钩子规则
if v, ok := mux.pre_gm[r.Method]; ok {
for prefix, proc := range v {
if strings.HasPrefix(r.URL.Path, prefix) {
if !proc.h.PreServeHTTP(pctx) {
return
}
}
}
}
//匹配固定URL规则
if v, ok := mux.gm[r.Method][r.URL.Path]; ok {
v.h.ServeHTTP(pctx)
return
}
//匹配智能URL规则
for _, v := range mux.im[r.Method] {
if strings.HasPrefix(r.URL.Path, v.pattern) {
urlParams := strings.Split(string([]byte(r.URL.Path)[len(v.pattern)+1:]), "/")
if len(urlParams) == len(v.urlParams) {
extURLParams := make(map[string]string)
foundSuss := true
for urlParamsID, urlParamsValue := range urlParams {
if strings.HasPrefix(v.urlParams[urlParamsID], ":") {
extURLParams[v.urlParams[urlParamsID]] = urlParamsValue
} else if urlParamsValue != v.urlParams[urlParamsID] {
foundSuss = false
break
}
}
if foundSuss {
pctx.urlParams = extURLParams
v.h.ServeHTTP(pctx)
return
}
}
}
}
//匹配静态路径规则
if r.Method == "GET" {
for pattern, path := range mux.pm {
if strings.HasPrefix(r.URL.Path, pattern) {
filePath := path + strings.TrimPrefix(r.URL.Path, pattern)
http.ServeFile(w, r, filePath)
return
}
}
}
if v, ok := mux.sm[http.StatusNotFound]; ok {
v.h.ServeHTTP(pctx)
}
}
func (mux *httpRouterHandler) RegHTTPPublic(pattern, path string) {
mux.mu.Lock()
defer mux.mu.Unlock()
if pattern == "" {
panic("http: invalid pattern")
}
if path == "" {
panic("http: invalid path")
}
if !strings.HasSuffix(pattern, "/") {
pattern += "/"
}
if !strings.HasSuffix(path, "/") {
path += "/"
}
//检查pattern是否之前已经添加过
if _, exist := mux.pm[pattern]; exist {
panic("http: multiple registrations for " + pattern)
}
if mux.pm == nil {
mux.pm = make(map[string]string)
}
mux.pm[pattern] = path
}
func (mux *httpRouterHandler) RegHTTPPreFunc(method, pattern string, handler preHttpProcFunc) {
mux.mu.Lock()
defer mux.mu.Unlock()
if pattern == "" {
panic("http: invalid pattern")
}
if handler == nil {
panic("http: nil handler")
}
//检查pattern是否之前已经添加过
if _, exist := mux.pre_gm[pattern]; exist {
panic("http: multiple registrations for " + pattern)
}
if mux.pre_gm == nil {
mux.pre_gm = make(map[string]map[string]preMuxEntry)
}
if mux.pre_gm[method] == nil {
mux.pre_gm[method] = make(map[string]preMuxEntry)
}
mux.pre_gm[method][pattern] = preMuxEntry{h: handler, pattern: pattern}
}
// RegHTTPProcFunc 注册固定URL、解析URL函数
// method string: 请求方式,POST、GET、PUT、DELETE等
// pattern string:触发路径
// handler httpProcFunc: 触发函数
func (mux *httpRouterHandler) RegHTTPProcFunc(method, pattern string, handler HttpProcFunc) {
mux.mu.Lock()
defer mux.mu.Unlock()
if pattern == "" {
panic("http: invalid pattern")
}
if handler == nil {
panic("http: nil handler")
}
//检查pattern是否之前已经添加过
if _, exist := mux.gm[pattern]; exist {
panic("http: multiple registrations for " + pattern)
}
if _, exist := mux.im[pattern]; exist {
panic("http: multiple registrations for " + pattern)
}
if mux.gm == nil {
mux.gm = make(map[string]map[string]muxEntry)
}
if mux.gm[method] == nil {
mux.gm[method] = make(map[string]muxEntry)
}
if mux.im == nil {
mux.im = make(map[string][]imuxEntry)
}
if mux.im[method] == nil {
mux.im[method] = []imuxEntry{}
}
istart := strings.Index(pattern, "/:")
if istart == -1 {
mux.gm[method][pattern] = muxEntry{h: handler, pattern: pattern}
} else {
if istart <= 1 {
fmt.Println(pattern + "错误,请不要以\\:开头!")
} else {
ipattern := string([]byte(pattern)[:istart])
urlParams := strings.Split(string([]byte(pattern)[istart+1:]), "/")
mux.im[method] = append(mux.im[method], imuxEntry{h: handler, urlParams: urlParams, pattern: ipattern})
}
}
/*if pattern[0] != '/' {
mux.hosts = true
}*/
}
// RegHTTPStatusFunc 注册指定HTTP状态触发的函数
// status int: HTTP状态, 参考net\http\status.go
// handler httpProcFunc: 触发函数
func (mux *httpRouterHandler) RegHTTPStatusFunc(status int, handler HttpProcFunc) {
mux.mu.Lock()
defer mux.mu.Unlock()
if status == 0 {
panic("http: invalid status")
}
if handler == nil {
panic("http: nil handler")
}
if mux.sm == nil {
mux.sm = make(map[int]muxEntry)
}
mux.sm[status] = muxEntry{h: handler, pattern: "404"}
}
Go
1
https://gitee.com/konyshe/gogo.git
git@gitee.com:konyshe/gogo.git
konyshe
gogo
gogo
v2

搜索帮助