Files
goproxy/internal/router/router.go
2025-03-13 15:56:33 +08:00

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
}