mirror of
https://gitee.com/johng/gf.git
synced 2024-12-05 13:48:09 +08:00
295 lines
8.5 KiB
Go
295 lines
8.5 KiB
Go
package ghttp
|
||
|
||
import (
|
||
"net/http"
|
||
"strings"
|
||
"path/filepath"
|
||
"crypto/tls"
|
||
"time"
|
||
"log"
|
||
"sync"
|
||
"errors"
|
||
"gitee.com/johng/gf/g/container/gmap"
|
||
)
|
||
|
||
const (
|
||
gDEFAULT_DOMAIN = "default"
|
||
gDEFAULT_METHOD = "all"
|
||
)
|
||
|
||
// http server结构体
|
||
type Server struct {
|
||
hmu sync.RWMutex // handlerMap互斥锁
|
||
name string // 服务名称,方便识别
|
||
server http.Server // 底层http server对象
|
||
config ServerConfig // 配置对象
|
||
handlerMap HandlerMap // 回调函数
|
||
status int8 // 当前服务器状态(0:未启动,1:运行中)
|
||
}
|
||
|
||
// 域名、URI与回调函数的绑定记录表
|
||
type HandlerMap map[string]HandlerFunc
|
||
|
||
// http回调函数
|
||
type HandlerFunc func(*ClientRequest, *ServerResponse)
|
||
|
||
// Server表,用以存储和检索名称与Server对象之间的关联关系
|
||
var serverMapping *gmap.StringInterfaceMap = gmap.NewStringInterfaceMap()
|
||
|
||
// 创建一个默认配置的HTTP Server(默认监听端口是80)
|
||
func GetServer(name string) (*Server) {
|
||
if s := serverMapping.Get(name); s != nil {
|
||
return s.(*Server)
|
||
}
|
||
s := &Server{}
|
||
s.name = name
|
||
s.handlerMap = make(HandlerMap)
|
||
s.SetConfig(defaultServerConfig)
|
||
serverMapping.Set(name, s)
|
||
return s
|
||
}
|
||
|
||
// 执行
|
||
func (s *Server) Run() error {
|
||
if s.status == 1 {
|
||
return errors.New("server is already running")
|
||
}
|
||
|
||
// 底层http server配置
|
||
if s.config.Handler == nil {
|
||
s.config.Handler = http.HandlerFunc(s.defaultHttpHandle)
|
||
}
|
||
// 底层http server初始化
|
||
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,
|
||
}
|
||
// 执行端口监听
|
||
if err := s.server.ListenAndServe(); err != nil {
|
||
return err
|
||
}
|
||
s.status = 1
|
||
return nil
|
||
}
|
||
|
||
// http server setting设置
|
||
// 注意使用该方法进行http server配置时,需要配置所有的配置项,否则没有配置的属性将会默认变量为空
|
||
func (s *Server)SetConfig(c ServerConfig) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
if c.Handler == nil {
|
||
c.Handler = http.HandlerFunc(s.defaultHttpHandle)
|
||
}
|
||
s.config = c
|
||
// 需要处理server root最后的目录分隔符号
|
||
if s.config.ServerRoot != "" {
|
||
s.SetServerRoot(s.config.ServerRoot)
|
||
}
|
||
// 必需设置默认值的属性
|
||
if len(s.config.IndexFiles) < 1 {
|
||
s.SetIndexFiles(defaultServerConfig.IndexFiles)
|
||
}
|
||
if s.config.ServerAgent == "" {
|
||
s.SetServerAgent(defaultServerConfig.ServerAgent)
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - Addr
|
||
func (s *Server)SetAddr(addr string) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.Addr = addr
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - TLSConfig
|
||
func (s *Server)SetTLSConfig(tls *tls.Config) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.TLSConfig = tls
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - ReadTimeout
|
||
func (s *Server)SetReadTimeout(t time.Duration) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.ReadTimeout = t
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - WriteTimeout
|
||
func (s *Server)SetWriteTimeout(t time.Duration) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.WriteTimeout = t
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - IdleTimeout
|
||
func (s *Server)SetIdleTimeout(t time.Duration) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.IdleTimeout = t
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - MaxHeaderBytes
|
||
func (s *Server)SetMaxHeaderBytes(b int) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.MaxHeaderBytes = b
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - ErrorLog
|
||
func (s *Server)SetErrorLog(logger *log.Logger) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.ErrorLog = logger
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - IndexFiles
|
||
func (s *Server)SetIndexFiles(index []string) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.IndexFiles = index
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - IndexFolder
|
||
func (s *Server)SetIndexFolder(index bool) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.IndexFolder = index
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - ServerAgent
|
||
func (s *Server)SetServerAgent(agent string) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.ServerAgent = agent
|
||
return nil
|
||
}
|
||
|
||
// 设置http server参数 - ServerRoot
|
||
func (s *Server)SetServerRoot(root string) error {
|
||
if s.status == 1 {
|
||
return errors.New("server config cannot be changed while running")
|
||
}
|
||
s.config.ServerRoot = strings.TrimRight(root, string(filepath.Separator))
|
||
return nil
|
||
}
|
||
|
||
// 生成回调方法查询的Key
|
||
func (s *Server) handlerKey(domain, method, pattern string) string {
|
||
return strings.ToUpper(method) + ":" + pattern + "@" + strings.ToLower(domain)
|
||
}
|
||
|
||
// 设置请求处理方法
|
||
func (s *Server) setHandler(domain, method, pattern string, handler HandlerFunc) {
|
||
s.hmu.Lock()
|
||
defer s.hmu.Unlock()
|
||
if method == "all" {
|
||
s.handlerMap[s.handlerKey(domain, "GET", pattern)] = handler
|
||
s.handlerMap[s.handlerKey(domain, "PUT", pattern)] = handler
|
||
s.handlerMap[s.handlerKey(domain, "POST", pattern)] = handler
|
||
s.handlerMap[s.handlerKey(domain, "DELETE", pattern)] = handler
|
||
s.handlerMap[s.handlerKey(domain, "PATCH", pattern)] = handler
|
||
s.handlerMap[s.handlerKey(domain, "HEAD", pattern)] = handler
|
||
s.handlerMap[s.handlerKey(domain, "CONNECT", pattern)] = handler
|
||
s.handlerMap[s.handlerKey(domain, "OPTIONS", pattern)] = handler
|
||
s.handlerMap[s.handlerKey(domain, "TRACE", pattern)] = handler
|
||
} else {
|
||
s.handlerMap[s.handlerKey(domain, method, pattern)] = handler
|
||
}
|
||
}
|
||
|
||
// 查询请求处理方法
|
||
func (s *Server) getHandler(domain, method, pattern string) HandlerFunc {
|
||
s.hmu.RLock()
|
||
defer s.hmu.RUnlock()
|
||
key := s.handlerKey(domain, method, pattern)
|
||
if f, ok := s.handlerMap[key]; ok {
|
||
return f
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 绑定URI到操作函数/方法
|
||
// pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn
|
||
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
||
func (s *Server)BindHandler(pattern string, handler HandlerFunc) error {
|
||
if s.status == 1 {
|
||
return errors.New("server handlers cannot be changed while running")
|
||
}
|
||
|
||
s.hmu.Lock()
|
||
defer s.hmu.Unlock()
|
||
|
||
uri := ""
|
||
domain := gDEFAULT_DOMAIN
|
||
method := "all"
|
||
result := strings.Split(pattern, "@")
|
||
if len(result) > 1 {
|
||
domain = result[1]
|
||
}
|
||
result = strings.Split(result[0], ":")
|
||
if len(result) > 1 {
|
||
method = result[0]
|
||
uri = result[0]
|
||
} else {
|
||
uri = result[0]
|
||
}
|
||
if uri == "" {
|
||
return errors.New("invalid pattern")
|
||
}
|
||
s.setHandler(domain, method, uri, handler)
|
||
return nil
|
||
}
|
||
|
||
// 通过映射数组绑定URI到操作函数/方法
|
||
func (s *Server)BindHandlerByMap(m HandlerMap) error {
|
||
for p, f := range m {
|
||
if err := s.BindHandler(p, f); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// 绑定控制器,控制器需要继承gmvc.Controller对象并实现需要的REST方法
|
||
func (s *Server)BindControllerRest(uri string, c ControllerRest) error {
|
||
return s.BindHandlerByMap(HandlerMap{
|
||
"GET:" + uri : c.Get,
|
||
"PUT:" + uri : c.Put,
|
||
"POST:" + uri : c.Post,
|
||
"DELETE:" + uri : c.Delete,
|
||
"PATCH:" + uri : c.Patch,
|
||
"HEAD:" + uri : c.Head,
|
||
"CONNECT:" + uri : c.Connect,
|
||
"OPTIONS:" + uri : c.Options,
|
||
"TRACE:" + uri : c.Trace,
|
||
})
|
||
}
|
||
|
||
|