gf/g/net/ghttp/http_server.go

309 lines
9.1 KiB
Go
Raw Normal View History

2017-11-23 10:21:28 +08:00
package ghttp
import (
"net/http"
"strings"
"path/filepath"
"crypto/tls"
"time"
"log"
2017-12-07 14:57:16 +08:00
"sync"
"errors"
"reflect"
"gitee.com/johng/gf/g/util/gutil"
2017-12-08 12:03:21 +08:00
"gitee.com/johng/gf/g/container/gmap"
2017-11-23 10:21:28 +08:00
)
const (
gDEFAULT_DOMAIN = "default"
gDEFAULT_METHOD = "all"
)
2017-12-07 14:57:16 +08:00
// http server结构体
type Server struct {
hmu sync.RWMutex // handlerMap互斥锁
2017-12-08 12:03:21 +08:00
name string // 服务名称,方便识别
2017-12-07 14:57:16 +08:00
server http.Server // 底层http server对象
config ServerConfig // 配置对象
handlerMap HandlerMap // 回调函数
2017-12-07 17:34:51 +08:00
status int8 // 当前服务器状态(0未启动1运行中)
2017-12-07 14:57:16 +08:00
}
// 域名、URI与回调函数的绑定记录表
type HandlerMap map[string]HandlerFunc
// http回调函数信息
type HandlerFunc struct {
ctype reflect.Type // 控制器类型
fname string // 回调方法名称
}
2017-12-07 14:57:16 +08:00
2017-12-08 12:03:21 +08:00
// Server表用以存储和检索名称与Server对象之间的关联关系
var serverMapping *gmap.StringInterfaceMap = gmap.NewStringInterfaceMap()
2017-12-07 17:34:51 +08:00
2017-12-07 14:57:16 +08:00
// 创建一个默认配置的HTTP Server(默认监听端口是80)
2017-12-07 17:34:51 +08:00
func GetServer(name string) (*Server) {
2017-12-08 12:03:21 +08:00
if s := serverMapping.Get(name); s != nil {
return s.(*Server)
2017-12-07 17:34:51 +08:00
}
s := &Server{}
s.name = name
s.handlerMap = make(HandlerMap)
2017-12-08 12:03:21 +08:00
s.SetConfig(defaultServerConfig)
serverMapping.Set(name, s)
return s
2017-12-07 14:57:16 +08:00
}
2017-11-23 10:21:28 +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,
}
// 执行端口监听
2017-12-07 14:57:16 +08:00
if err := s.server.ListenAndServe(); err != nil {
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
2017-11-23 10:21:28 +08:00
}
// http server setting设置
// 注意使用该方法进行http server配置时需要配置所有的配置项否则没有配置的属性将会默认变量为空
2017-12-07 17:34:51 +08:00
func (s *Server)SetConfig(c ServerConfig) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
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)
}
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - Addr
2017-12-07 17:34:51 +08:00
func (s *Server)SetAddr(addr string) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.Addr = addr
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - TLSConfig
2017-12-07 17:34:51 +08:00
func (s *Server)SetTLSConfig(tls *tls.Config) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.TLSConfig = tls
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - ReadTimeout
2017-12-07 17:34:51 +08:00
func (s *Server)SetReadTimeout(t time.Duration) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.ReadTimeout = t
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - WriteTimeout
2017-12-07 17:34:51 +08:00
func (s *Server)SetWriteTimeout(t time.Duration) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.WriteTimeout = t
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - IdleTimeout
2017-12-07 17:34:51 +08:00
func (s *Server)SetIdleTimeout(t time.Duration) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.IdleTimeout = t
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - MaxHeaderBytes
2017-12-07 17:34:51 +08:00
func (s *Server)SetMaxHeaderBytes(b int) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.MaxHeaderBytes = b
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - ErrorLog
2017-12-07 17:34:51 +08:00
func (s *Server)SetErrorLog(logger *log.Logger) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.ErrorLog = logger
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - IndexFiles
2017-12-07 17:34:51 +08:00
func (s *Server)SetIndexFiles(index []string) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.IndexFiles = index
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - IndexFolder
2017-12-07 17:34:51 +08:00
func (s *Server)SetIndexFolder(index bool) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.IndexFolder = index
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - ServerAgent
2017-12-07 17:34:51 +08:00
func (s *Server)SetServerAgent(agent string) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.ServerAgent = agent
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 设置http server参数 - ServerRoot
2017-12-07 17:34:51 +08:00
func (s *Server)SetServerRoot(root string) error {
if s.status == 1 {
return errors.New("server config cannot be changed while running")
}
2017-11-23 10:21:28 +08:00
s.config.ServerRoot = strings.TrimRight(root, string(filepath.Separator))
2017-12-07 17:34:51 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 生成回调方法查询的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()
2017-12-11 18:21:30 +08:00
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
}
2017-11-23 10:21:28 +08:00
// 绑定URI到操作函数/方法
// pattern的格式形如/user/list, put:/user, delete:/user, post:/user@johng.cn
2017-11-23 10:21:28 +08:00
// 支持RESTful的请求格式具体业务逻辑由绑定的处理方法来执行
func (s *Server)bindHandler(pattern string, handler HandlerFunc) error {
2017-12-07 17:34:51 +08:00
if s.status == 1 {
return errors.New("server handlers cannot be changed while running")
}
uri := ""
domain := gDEFAULT_DOMAIN
2017-12-11 18:21:30 +08:00
method := "all"
result := strings.Split(pattern, "@")
if len(result) > 1 {
domain = result[1]
2017-11-23 10:21:28 +08:00
}
result = strings.Split(result[0], ":")
2017-11-23 10:21:28 +08:00
if len(result) > 1 {
method = result[0]
uri = result[0]
2017-11-23 10:21:28 +08:00
} else {
uri = result[0]
2017-11-23 10:21:28 +08:00
}
if uri == "" {
return errors.New("invalid pattern")
2017-11-23 10:21:28 +08:00
}
s.setHandler(domain, method, uri, handler)
2017-12-07 14:57:16 +08:00
return nil
2017-11-23 10:21:28 +08:00
}
// 通过映射数组绑定URI到操作函数/方法
func (s *Server)bindHandlerByMap(m HandlerMap) error {
for p, h := range m {
if err := s.bindHandler(p, h); err != nil {
return err
}
2017-11-23 10:21:28 +08:00
}
return nil
2017-11-23 10:21:28 +08:00
}
// 绑定方法pattern支持http method
// pattern的格式形如/user/list, put:/user, delete:/user
func (s *Server)BindMethod(pattern string, c Controller, method string) error {
return s.bindHandler(pattern, HandlerFunc{reflect.ValueOf(c).Type(), method})
2017-11-23 10:21:28 +08:00
}
// 绑定控制器控制器需要实现gmvc.Controller接口
func (s *Server)BindController(uri string, c Controller) error {
// 遍历控制器获取方法列表并构造成uri
m := make(HandlerMap)
v := reflect.ValueOf(c)
t := v.Type()
for i := 0; i < v.NumMethod(); i++ {
key := strings.TrimRight(uri, "/") + "/"
name := t.Method(i).Name
if name == "Init" || name == "Shut" {
continue
}
for i := 0; i < len(name); i++ {
if i > 0 && gutil.IsLetterUpper(name[i]) {
key += "-"
}
key += strings.ToLower(string(name[i]))
}
m[key] = HandlerFunc{t, name}
}
//fmt.Println(m)
return s.bindHandlerByMap(m)
}