代码拉取完成,页面将自动刷新
package msgo
import (
"fmt"
"gitee.com/MrDaiM/msgo/config"
"gitee.com/MrDaiM/msgo/gateway"
msgLog "gitee.com/MrDaiM/msgo/log"
"gitee.com/MrDaiM/msgo/register"
"gitee.com/MrDaiM/msgo/render"
"html/template"
"log"
"net/http"
"net/http/httputil"
"net/url"
"sync"
)
const ANY = "ANY"
type HandlerFunc func(ctx *Context)
type MiddlewareFunc func(handlerFunc HandlerFunc) HandlerFunc
type router struct {
routerGroups []*routerGroup
engine *Engine
}
func (r *router) Group(name string) *routerGroup {
g := &routerGroup{
name: name,
handleFuncMap: make(map[string]map[string]HandlerFunc),
handlerMethodMap: make(map[string][]string),
middlewaresFuncMap: make(map[string]map[string][]MiddlewareFunc),
treeNode: &treeNode{name: "/", children: make([]*treeNode, 0)},
}
// 一旦创建 group 那么就设置好中间件
g.Use(r.engine.middles...) // 提供 默认的 中间件
r.routerGroups = append(r.routerGroups, g)
return g
}
// ErrorHandler int 返回的状态 any 返回的错误信息
type ErrorHandler func(err error) (int, any)
type Engine struct {
router
funcMap template.FuncMap // 存放自定义函数
HTMLRender render.HTMLRender // 存放模版
pool sync.Pool // 防止频繁创建context
Logger *msgLog.Logger
middles []MiddlewareFunc
errorHandler ErrorHandler
OpenGateWay bool
gatewayConfigs []gateway.GWConfig
gatewayTreeNode *gateway.TreeNode
gatewayConfigMap map[string]gateway.GWConfig
RegisterType string
RegisterOption register.Option
RegisterCli register.MsRegister
}
func New() *Engine {
engine := &Engine{
router: router{},
funcMap: nil,
HTMLRender: render.HTMLRender{},
gatewayTreeNode: &gateway.TreeNode{Name: "/", Children: make([]*gateway.TreeNode, 0)},
gatewayConfigMap: make(map[string]gateway.GWConfig),
}
engine.pool.New = func() any {
return engine.allocateContext()
}
return engine
}
func Default() *Engine {
engine := New()
engine.Logger = msgLog.Default()
logPath, ok := config.Conf.Log["path"]
if ok {
engine.Logger.SetLogPath(logPath.(string))
}
engine.Use(Logging, Recovery) // 暂时存一下,传递给group 进行中间件设置 将中间件绑定到路由引擎上, 提前设置好固定的中间件
engine.router.engine = engine
return engine
}
func (e *Engine) allocateContext() any {
return &Context{engine: e}
}
func (e *Engine) SetGatewayConfig(configs []gateway.GWConfig) {
e.gatewayConfigs = configs
// 把这个路径存储起来 访问的时候去匹配这里面的路由, 如果匹配,就拿出来相应的匹配结果
for _, v := range e.gatewayConfigs {
e.gatewayTreeNode.Put(v.Path, v.Name)
e.gatewayConfigMap[v.Name] = v
}
fmt.Println(e)
}
func (e *Engine) SetFuncMap(funcMap template.FuncMap) {
e.funcMap = funcMap
}
// LoadTemplate 加载所有模板
func (e *Engine) LoadTemplate(pattern string) {
t := template.Must(template.New("").Funcs(e.funcMap).ParseGlob(pattern))
e.SetHtmlTemplate(t)
}
func (e *Engine) LoadTemplateConf() {
pattern, ok := config.Conf.Template["pattern"]
if ok {
t := template.Must(template.New("").Funcs(e.funcMap).ParseGlob(pattern.(string)))
e.SetHtmlTemplate(t)
}
}
// SetHtmlTemplate 提供自定义的设置方法
func (e *Engine) SetHtmlTemplate(t *template.Template) {
e.HTMLRender = render.HTMLRender{Template: t}
}
func (e *Engine) Handler() http.Handler {
return e
}
func (e *Engine) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
// 获取后重新赋值
ctx := e.pool.Get().(*Context)
ctx.W = writer
ctx.R = request
ctx.Logger = e.Logger
e.httpRequestHandle(ctx, writer, request)
// 放回缓存中区
e.pool.Put(ctx)
}
func (e *Engine) httpRequestHandle(ctx *Context, writer http.ResponseWriter, request *http.Request) {
if e.OpenGateWay {
// 请i去过来, 具体转发到哪里
path := request.URL.Path
node := e.gatewayTreeNode.Get(path)
if node == nil {
ctx.W.WriteHeader(http.StatusNotFound)
_, _ = fmt.Fprintln(ctx.W, ctx.R.RequestURI+" not found")
return
}
// 获取网关的配置
gwConfig := e.gatewayConfigMap[node.GwName]
// 调用外部提供的方法,设置请求头(这样就可以接受外部更改请求头)
gwConfig.Header(ctx.R)
// 目标请求路径(url 解析)
addr, err := e.RegisterCli.GetValue(gwConfig.ServiceName)
if err != nil {
ctx.W.WriteHeader(http.StatusInternalServerError)
_, _ = fmt.Fprintln(ctx.W, err.Error())
return
}
//target, err := url.Parse(fmt.Sprintf("http://%s:%d%s", gwConfig.Host, gwConfig.Port, path))
target, err := url.Parse(fmt.Sprintf("http://%s%s", addr, path))
if err != nil {
ctx.W.WriteHeader(http.StatusInternalServerError)
_, _ = fmt.Fprintln(ctx.W, err.Error())
return
}
// director, response, handler 可以提供出去让外部去拓展
// 网关的处理逻辑
director := func(req *http.Request) {
// 将原因有请求进行替换
req.Host = request.Host
req.URL.Host = target.Host
req.URL.Path = target.Path
req.URL.Scheme = target.Scheme
if _, ok := req.Header["User-Agent"]; !ok { // 如果没有值可以空值,否则无法识别
req.Header.Set("User-Agent", "")
}
}
response := func(response *http.Response) error {
log.Println("响应修改")
return nil
}
handler := func(writer http.ResponseWriter, request *http.Request, err error) {
log.Println("错误处理")
}
proxy := httputil.ReverseProxy{Director: director, ModifyResponse: response, ErrorHandler: handler}
// 代理
proxy.ServeHTTP(writer, request)
return
}
method := request.Method
for _, group := range e.routerGroups {
log.Println(request.URL.Path) // 不携带参数 /user/string
log.Println(request.RequestURI) // 携带参数 /user/string?id=1
routerName := SubStringLast(request.URL.Path, "/"+group.name)
// get/1
node := group.treeNode.Get(routerName)
if node == nil || !node.isEnd {
writer.WriteHeader(http.StatusNotFound)
fmt.Fprintln(writer, request.RequestURI+" not found")
return
}
if node != nil {
// 路由匹配上了
//ctx := &Context{
// W: writer,
// R: request,
// engine: e,
//}
// 检测是否有ANY的请求方式
handle, ok := group.handleFuncMap[node.routerName][ANY]
if ok {
//handle(ctx)
group.methodHandle(node.routerName, method, handle, ctx)
return
}
// 其他的请求方式
handle, ok = group.handleFuncMap[node.routerName][method]
if ok {
//handle(ctx)
group.methodHandle(node.routerName, method, handle, ctx)
return
}
writer.WriteHeader(http.StatusMethodNotAllowed)
_, _ = fmt.Fprintf(writer, "%s %s not allowed \n", request.RequestURI, method)
return
}
}
writer.WriteHeader(http.StatusNotFound)
_, _ = fmt.Fprintf(writer, "%s not found \n", request.RequestURI)
}
func (e *Engine) RunTLS(addr, cetFile, keyFile string) {
err := http.ListenAndServeTLS(addr, cetFile, keyFile, e.Handler())
if err != nil {
log.Fatal(err)
}
}
func (e *Engine) Run(addr string) {
if e.RegisterType == "nacos" {
nacosRegister := register.MsNacosRegister{}
err := nacosRegister.CreateCli(e.RegisterOption)
if err != nil {
panic(err)
}
e.RegisterCli = &nacosRegister
}
if e.RegisterType == "etcd" {
etcdRegister := register.MsETCDRegister{}
err := etcdRegister.CreateCli(e.RegisterOption)
if err != nil {
panic(err)
}
e.RegisterCli = &etcdRegister
}
http.Handle("/", e) // Handle 需要实现协议的方法 ServeHTTP
err := http.ListenAndServe(addr, nil)
if err != nil {
log.Fatal(err)
}
}
func (e *Engine) Use(middles ...MiddlewareFunc) {
e.middles = append(e.middles, middles...)
}
func (e *Engine) RegisterErrorHandler(handler ErrorHandler) {
e.errorHandler = handler
}
type routerGroup struct {
name string
handleFuncMap map[string]map[string]HandlerFunc // key:请求路径 value: 支持同一个路径不同请求方式
middlewaresFuncMap map[string]map[string][]MiddlewareFunc // 函数级中间件 key:string(请求路径) value:map[string][]MiddlewareFunc 请求方法:函数结构
handlerMethodMap map[string][]string // Key:GET、POST、PUT value:["path","path"]
treeNode *treeNode
middlewareMap map[string]map[string][]MiddlewareFunc
middlewares []MiddlewareFunc
}
func (r *routerGroup) Use(middlewares ...MiddlewareFunc) {
r.middlewares = append(r.middlewares, middlewares...)
}
func (r *routerGroup) methodHandle(name string, method string, handlerFunc HandlerFunc, ctx *Context) {
// 组通用中间件
if r.middlewares != nil {
for _, middleFunc := range r.middlewares {
handlerFunc = middleFunc(handlerFunc)
}
}
// 组路由级别中间件 方法级
middlewareFuncs := r.middlewaresFuncMap[name][method]
if middlewareFuncs != nil {
for _, middlewareFunc := range middlewareFuncs {
handlerFunc = middlewareFunc(handlerFunc)
}
}
// 正常执行逻辑
handlerFunc(ctx)
}
func (r *routerGroup) handle(name string, method string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
_, ok := r.handleFuncMap[name]
if !ok {
r.handleFuncMap[name] = make(map[string]HandlerFunc)
// 添加函数级别的中间件
r.middlewaresFuncMap[name] = make(map[string][]MiddlewareFunc)
}
_, ok = r.handleFuncMap[name][method]
if ok {
panic("有重复的路由")
}
// name 是请求路径, method 是请求方式, 可以有不多的请求方式
r.handleFuncMap[name][method] = handlerFunc
// 添加方法级的中间件
r.middlewaresFuncMap[name][method] = append(r.middlewaresFuncMap[name][method], middlewareFunc...)
// 请求方法对用的完整路径 ??? 似乎没有用处了
r.handlerMethodMap[method] = append(r.handlerMethodMap[method], name)
// 添加节点
r.treeNode.Put(name)
}
func (r *routerGroup) Handle(name string, method string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
// method 有效性校验
r.handle(name, method, handlerFunc, middlewareFunc...)
}
func (r *routerGroup) Any(name string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
r.handle(name, ANY, handlerFunc, middlewareFunc...)
}
func (r *routerGroup) Get(name string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
r.handle(name, http.MethodGet, handlerFunc, middlewareFunc...)
}
func (r *routerGroup) Post(name string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
r.handle(name, http.MethodPost, handlerFunc, middlewareFunc...)
}
func (r *routerGroup) Delete(name string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
r.handle(name, http.MethodDelete, handlerFunc, middlewareFunc...)
}
func (r *routerGroup) Put(name string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
r.handle(name, http.MethodPut, handlerFunc, middlewareFunc...)
}
func (r *routerGroup) Patch(name string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
r.handle(name, http.MethodPatch, handlerFunc, middlewareFunc...)
}
func (r *routerGroup) Options(name string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
r.handle(name, http.MethodOptions, handlerFunc, middlewareFunc...)
}
func (r *routerGroup) Head(name string, handlerFunc HandlerFunc, middlewareFunc ...MiddlewareFunc) {
r.handle(name, http.MethodHead, handlerFunc, middlewareFunc...)
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。