104 lines
2.0 KiB
Go
104 lines
2.0 KiB
Go
package router
|
|
|
|
import (
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
// Route 路由规则
|
|
type Route struct {
|
|
// 匹配模式(主机名、路径、正则表达式)
|
|
Pattern string
|
|
// 匹配类型
|
|
Type RouteType
|
|
// 目标地址
|
|
Target string
|
|
// 路径重写规则
|
|
RewritePattern string
|
|
// 请求头修改
|
|
HeaderModifier HeaderModifier
|
|
// 自定义匹配函数
|
|
MatchFunc func(req *http.Request) bool
|
|
}
|
|
|
|
// RouteType 路由类型
|
|
type RouteType int
|
|
|
|
const (
|
|
// HostRoute 主机名路由
|
|
HostRoute RouteType = iota
|
|
// PathRoute 路径路由
|
|
PathRoute
|
|
// RegexRoute 正则表达式路由
|
|
RegexRoute
|
|
// CustomRoute 自定义路由
|
|
CustomRoute
|
|
)
|
|
|
|
// HeaderModifier 头部修改接口
|
|
type HeaderModifier interface {
|
|
// ModifyRequest 修改请求头
|
|
ModifyRequest(req *http.Request)
|
|
// ModifyResponse 修改响应头
|
|
ModifyResponse(resp *http.Response)
|
|
}
|
|
|
|
// Router 路由器
|
|
type Router struct {
|
|
routes []*Route
|
|
}
|
|
|
|
// NewRouter 创建路由器
|
|
func NewRouter() *Router {
|
|
return &Router{
|
|
routes: make([]*Route, 0),
|
|
}
|
|
}
|
|
|
|
// AddRoute 添加路由规则
|
|
func (r *Router) AddRoute(route *Route) {
|
|
r.routes = append(r.routes, route)
|
|
}
|
|
|
|
// Match 匹配请求
|
|
func (r *Router) Match(req *http.Request) (*Route, bool) {
|
|
for _, route := range r.routes {
|
|
switch route.Type {
|
|
case HostRoute:
|
|
if matchHost(req.Host, route.Pattern) {
|
|
return route, true
|
|
}
|
|
case PathRoute:
|
|
if matchPath(req.URL.Path, route.Pattern) {
|
|
return route, true
|
|
}
|
|
case RegexRoute:
|
|
if matchRegex(req.URL.String(), route.Pattern) {
|
|
return route, true
|
|
}
|
|
case CustomRoute:
|
|
if route.MatchFunc != nil && route.MatchFunc(req) {
|
|
return route, true
|
|
}
|
|
}
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
// 匹配主机名
|
|
func matchHost(host, pattern string) bool {
|
|
return host == pattern || strings.HasSuffix(host, "."+pattern)
|
|
}
|
|
|
|
// 匹配路径
|
|
func matchPath(path, pattern string) bool {
|
|
return strings.HasPrefix(path, pattern)
|
|
}
|
|
|
|
// 匹配正则表达式
|
|
func matchRegex(url, pattern string) bool {
|
|
matched, _ := regexp.MatchString(pattern, url)
|
|
return matched
|
|
}
|