gf/g/net/ghttp/http_server.go
2017-12-11 18:21:30 +08:00

295 lines
8.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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,
})
}