gf/g/net/ghttp/http_server.go

179 lines
7.1 KiB
Go
Raw Normal View History

2017-12-29 16:03:30 +08:00
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
2017-11-23 10:21:28 +08:00
package ghttp
import (
2017-12-07 14:57:16 +08:00
"sync"
"errors"
2018-04-10 10:32:37 +08:00
"strings"
"reflect"
2017-12-26 11:46:48 +08:00
"net/http"
"gitee.com/johng/gf/g/os/glog"
2018-04-11 16:06:45 +08:00
"gitee.com/johng/gf/g/os/gcache"
2018-04-20 23:23:42 +08:00
"gitee.com/johng/gf/g/util/gconv"
"gitee.com/johng/gf/g/container/gmap"
"gitee.com/johng/gf/g/container/gtype"
2018-04-11 16:06:45 +08:00
"gitee.com/johng/gf/g/container/gqueue"
2017-11-23 10:21:28 +08:00
)
const (
gHTTP_METHODS = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE"
2018-04-10 10:32:37 +08:00
gDEFAULT_SERVER = "default"
gDEFAULT_DOMAIN = "default"
2018-04-12 14:09:33 +08:00
gDEFAULT_METHOD = "ALL"
2018-04-10 10:32:37 +08:00
gDEFAULT_COOKIE_PATH = "/" // 默认path
gDEFAULT_COOKIE_MAX_AGE = 86400*365 // 默认cookie有效期(一年)
gDEFAULT_SESSION_MAX_AGE = 600 // 默认session有效期(600秒)
gDEFAULT_SESSION_ID_NAME = "gfsessionid" // 默认存放Cookie中的SessionId名称
)
2017-12-07 14:57:16 +08:00
// http server结构体
type Server struct {
hmmu sync.RWMutex // handler互斥锁
hhmu sync.RWMutex // hooks互斥锁
hmcmu sync.RWMutex // handlerCache互斥锁
hhcmu sync.RWMutex // hooksCache互斥锁
name string // 服务名称,方便识别
server http.Server // 底层http server对象
config ServerConfig // 配置对象
status int8 // 当前服务器状态(0未启动1运行中)
methodsMap map[string]bool // 所有支持的HTTP Method(初始化时自动填充)
handlerMap HandlerMap // 所有注册的回调函数(静态匹配)
handlerTree map[string]interface{} // 所有注册的回调函数(动态匹配,树型+链表优先级匹配)
hooksTree map[string]interface{} // 所有注册的事件回调函数(动态匹配,树型+链表优先级匹配)
handlerCache *gcache.Cache // 服务注册路由内存缓存
hooksCache *gcache.Cache // 回调事件注册路由内存缓存
servedCount *gtype.Int // 已经服务的请求数(4-8字节不考虑溢出情况)
cookieMaxAge *gtype.Int // Cookie有效期
sessionMaxAge *gtype.Int // Session有效期
sessionIdName *gtype.String // SessionId名称
cookies *gmap.IntInterfaceMap // 当前服务器正在服务(请求正在执行)的Cookie(每个请求一个Cookie对象)
sessions *gcache.Cache // Session内存缓存
closeQueue *gqueue.Queue // 请求结束的关闭队列(存放的是需要异步关闭处理的*Request对象)
logPath *gtype.String // 存放日志的目录路径
errorLogEnabled *gtype.Bool // 是否开启error log
accessLogEnabled *gtype.Bool // 是否开启access log
2018-04-20 18:12:47 +08:00
accessLogger *glog.Logger // access log日志对象
errorLogger *glog.Logger // error log日志对象
logHandler *gtype.Interface // 自定义的日志处理回调方法
2017-12-07 14:57:16 +08:00
}
// 域名、URI与回调函数的绑定记录表
2018-04-12 14:09:33 +08:00
type HandlerMap map[string]*HandlerItem
// 路由对象
type Router struct {
Uri string // 注册时的pattern - uri
Method string // 注册时的pattern - method
Domain string // 注册时的pattern - domain
Priority int // 优先级,用于链表排序,值越大优先级越高
}
// http回调函数注册信息
2017-12-26 10:13:49 +08:00
type HandlerItem struct {
2018-04-12 14:09:33 +08:00
ctype reflect.Type // 控制器类型
fname string // 回调方法名称
faddr HandlerFunc // 准确的执行方法内存地址(与以上两个参数二选一)
router *Router // 注册时绑定的路由对象
}
2017-12-07 14:57:16 +08:00
2017-12-26 10:13:49 +08:00
// http注册函数
type HandlerFunc func(*Request)
2017-12-26 10:13:49 +08:00
2017-12-08 12:03:21 +08:00
// Server表用以存储和检索名称与Server对象之间的关联关系
var serverMapping = gmap.NewStringInterfaceMap()
2017-12-07 17:34:51 +08:00
// 获取/创建一个默认配置的HTTP Server(默认监听端口是80)
// 单例模式请保证name的唯一性
2018-04-20 23:23:42 +08:00
func GetServer(name...interface{}) (*Server) {
sname := gDEFAULT_SERVER
if len(name) > 0 {
sname = gconv.String(name[0])
2017-12-30 18:35:24 +08:00
}
2018-04-20 23:23:42 +08:00
if s := serverMapping.Get(sname); s != nil {
2017-12-08 12:03:21 +08:00
return s.(*Server)
2017-12-07 17:34:51 +08:00
}
2018-04-11 16:06:45 +08:00
s := &Server {
2018-04-20 23:23:42 +08:00
name : sname,
methodsMap : make(map[string]bool),
handlerMap : make(HandlerMap),
handlerTree : make(map[string]interface{}),
hooksTree : make(map[string]interface{}),
handlerCache : gcache.New(),
hooksCache : gcache.New(),
cookies : gmap.NewIntInterfaceMap(),
sessions : gcache.New(),
cookieMaxAge : gtype.NewInt(gDEFAULT_COOKIE_MAX_AGE),
sessionMaxAge : gtype.NewInt(gDEFAULT_SESSION_MAX_AGE),
sessionIdName : gtype.NewString(gDEFAULT_SESSION_ID_NAME),
servedCount : gtype.NewInt(),
closeQueue : gqueue.New(),
logPath : gtype.NewString(),
accessLogEnabled : gtype.NewBool(),
2018-04-23 11:20:48 +08:00
errorLogEnabled : gtype.NewBool(true),
2018-04-20 18:12:47 +08:00
accessLogger : glog.New(),
errorLogger : glog.New(),
logHandler : gtype.NewInterface(),
2017-12-30 17:09:00 +08:00
}
2018-04-20 18:12:47 +08:00
s.errorLogger.SetBacktraceSkip(4)
s.accessLogger.SetBacktraceSkip(4)
// 设置路由解析缓存上限使用LRU进行缓存淘汰
s.hooksCache.SetCap(10000)
s.handlerCache.SetCap(10000)
2017-12-26 11:46:48 +08:00
for _, v := range strings.Split(gHTTP_METHODS, ",") {
s.methodsMap[v] = true
}
2017-12-08 12:03:21 +08:00
s.SetConfig(defaultServerConfig)
2018-04-20 23:23:42 +08:00
serverMapping.Set(sname, s)
2017-12-08 12:03:21 +08:00
return s
2017-12-07 14:57:16 +08:00
}
2018-04-11 16:06:45 +08:00
// 阻塞执行监听
2017-12-07 17:34:51 +08:00
func (s *Server) Run() error {
2017-12-08 12:03:21 +08:00
if s.status == 1 {
return errors.New("server is already running")
}
2017-11-23 10:21:28 +08:00
// 底层http server配置
if s.config.Handler == nil {
s.config.Handler = http.HandlerFunc(s.defaultHttpHandle)
}
2017-12-07 14:57:16 +08:00
// 底层http server初始化
2017-11-23 10:21:28 +08:00
s.server = http.Server {
Addr : s.config.Addr,
Handler : s.config.Handler,
ReadTimeout : s.config.ReadTimeout,
WriteTimeout : s.config.WriteTimeout,
IdleTimeout : s.config.IdleTimeout,
MaxHeaderBytes : s.config.MaxHeaderBytes,
}
// 开启异步处理队列处理循环
s.startCloseQueueLoop()
2017-11-23 10:21:28 +08:00
// 执行端口监听
2017-12-07 14:57:16 +08:00
if err := s.server.ListenAndServe(); err != nil {
glog.Error(err)
2017-12-07 14:57:16 +08:00
return err
2017-11-23 10:21:28 +08:00
}
2017-12-07 17:34:51 +08:00
s.status = 1
2017-12-07 14:57:16 +08:00
return nil
}
// 清空当前的handlerCache
func (s *Server) clearHandlerCache() {
s.hmcmu.Lock()
defer s.hmcmu.Unlock()
s.handlerCache.Close()
s.handlerCache = gcache.New()
}
// 清空当前的hooksCache
func (s *Server) clearHooksCache() {
s.hhcmu.Lock()
defer s.hhcmu.Unlock()
s.hooksCache.Close()
s.hooksCache = gcache.New()
2018-04-13 15:19:31 +08:00
}