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"
|
2017-12-12 17:25:50 +08:00
|
|
|
|
"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
|
|
|
|
)
|
|
|
|
|
|
2017-12-11 17:16:59 +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
|
|
|
|
}
|
|
|
|
|
|
2017-12-11 17:16:59 +08:00
|
|
|
|
// 域名、URI与回调函数的绑定记录表
|
|
|
|
|
type HandlerMap map[string]HandlerFunc
|
|
|
|
|
|
2017-12-14 17:32:51 +08:00
|
|
|
|
// http回调函数注册信息
|
2017-12-12 17:25:50 +08:00
|
|
|
|
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对象之间的关联关系
|
2017-12-13 16:45:00 +08:00
|
|
|
|
var serverMapping = gmap.NewStringInterfaceMap()
|
2017-12-07 17:34:51 +08:00
|
|
|
|
|
2017-12-18 10:42:59 +08:00
|
|
|
|
// 获取/创建一个默认配置的HTTP Server(默认监听端口是80)
|
|
|
|
|
// 单例模式,请保证name的唯一性
|
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
|
|
|
|
}
|
2017-12-11 17:16:59 +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
|
|
|
|
}
|
|
|
|
|
|
2017-12-13 16:45:00 +08:00
|
|
|
|
// 获取
|
|
|
|
|
func (s *Server) GetName() string {
|
|
|
|
|
return s.name
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
2017-12-11 17:16:59 +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-13 11:36:29 +08:00
|
|
|
|
if method == gDEFAULT_METHOD {
|
2017-12-11 17:16:59 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 查询请求处理方法
|
2017-12-12 17:25:50 +08:00
|
|
|
|
func (s *Server) getHandler(domain, method, pattern string) *HandlerFunc {
|
2017-12-11 17:16:59 +08:00
|
|
|
|
s.hmu.RLock()
|
|
|
|
|
defer s.hmu.RUnlock()
|
|
|
|
|
key := s.handlerKey(domain, method, pattern)
|
|
|
|
|
if f, ok := s.handlerMap[key]; ok {
|
2017-12-12 17:25:50 +08:00
|
|
|
|
return &f
|
2017-12-11 17:16:59 +08:00
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-23 10:21:28 +08:00
|
|
|
|
// 绑定URI到操作函数/方法
|
2017-12-11 17:16:59 +08:00
|
|
|
|
// pattern的格式形如:/user/list, put:/user, delete:/user, post:/user@johng.cn
|
2017-11-23 10:21:28 +08:00
|
|
|
|
// 支持RESTful的请求格式,具体业务逻辑由绑定的处理方法来执行
|
2017-12-12 17:25:50 +08:00
|
|
|
|
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")
|
|
|
|
|
}
|
2017-12-11 17:16:59 +08:00
|
|
|
|
uri := ""
|
|
|
|
|
domain := gDEFAULT_DOMAIN
|
2017-12-11 18:21:30 +08:00
|
|
|
|
method := "all"
|
2017-12-11 17:16:59 +08:00
|
|
|
|
result := strings.Split(pattern, "@")
|
|
|
|
|
if len(result) > 1 {
|
|
|
|
|
domain = result[1]
|
2017-11-23 10:21:28 +08:00
|
|
|
|
}
|
2017-12-11 17:16:59 +08:00
|
|
|
|
result = strings.Split(result[0], ":")
|
2017-11-23 10:21:28 +08:00
|
|
|
|
if len(result) > 1 {
|
2017-12-11 17:16:59 +08:00
|
|
|
|
method = result[0]
|
|
|
|
|
uri = result[0]
|
2017-11-23 10:21:28 +08:00
|
|
|
|
} else {
|
2017-12-11 17:16:59 +08:00
|
|
|
|
uri = result[0]
|
2017-11-23 10:21:28 +08:00
|
|
|
|
}
|
2017-12-11 17:16:59 +08:00
|
|
|
|
if uri == "" {
|
|
|
|
|
return errors.New("invalid pattern")
|
2017-11-23 10:21:28 +08:00
|
|
|
|
}
|
2017-12-11 17:16:59 +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到操作函数/方法
|
2017-12-12 17:25:50 +08:00
|
|
|
|
func (s *Server)bindHandlerByMap(m HandlerMap) error {
|
|
|
|
|
for p, h := range m {
|
|
|
|
|
if err := s.bindHandler(p, h); err != nil {
|
2017-12-11 17:16:59 +08:00
|
|
|
|
return err
|
|
|
|
|
}
|
2017-11-23 10:21:28 +08:00
|
|
|
|
}
|
2017-12-11 17:16:59 +08:00
|
|
|
|
return nil
|
2017-11-23 10:21:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-12 17:25:50 +08:00
|
|
|
|
// 绑定方法,pattern支持http method
|
|
|
|
|
// pattern的格式形如:/user/list, put:/user, delete:/user
|
|
|
|
|
func (s *Server)BindMethod(pattern string, c Controller, method string) error {
|
2017-12-13 11:36:29 +08:00
|
|
|
|
return s.bindHandler(pattern, HandlerFunc{reflect.ValueOf(c).Elem().Type(), method})
|
2017-11-23 10:21:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2017-12-12 17:25:50 +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]))
|
|
|
|
|
}
|
2017-12-13 11:36:29 +08:00
|
|
|
|
m[key] = HandlerFunc{v.Elem().Type(), name}
|
2017-12-12 17:25:50 +08:00
|
|
|
|
}
|
|
|
|
|
return s.bindHandlerByMap(m)
|
|
|
|
|
}
|