2019-02-02 16:18:25 +08:00
|
|
|
|
// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
2017-12-29 16:03:30 +08:00
|
|
|
|
//
|
|
|
|
|
// 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,
|
2019-02-02 16:18:25 +08:00
|
|
|
|
// You can obtain one at https://github.com/gogf/gf.
|
2017-12-31 18:19:58 +08:00
|
|
|
|
|
2017-12-07 14:57:16 +08:00
|
|
|
|
package ghttp
|
|
|
|
|
|
|
|
|
|
import (
|
2019-06-19 09:06:52 +08:00
|
|
|
|
"crypto/tls"
|
|
|
|
|
"fmt"
|
|
|
|
|
"net/http"
|
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
2019-07-28 11:50:12 +08:00
|
|
|
|
|
2019-09-13 20:49:16 +08:00
|
|
|
|
"github.com/gogf/gf/util/gconv"
|
|
|
|
|
|
2019-09-11 21:19:45 +08:00
|
|
|
|
"github.com/gogf/gf/os/gsession"
|
|
|
|
|
|
2019-08-16 00:29:14 +08:00
|
|
|
|
"github.com/gogf/gf/os/gview"
|
|
|
|
|
|
2019-07-29 21:01:19 +08:00
|
|
|
|
"github.com/gogf/gf/os/gfile"
|
|
|
|
|
"github.com/gogf/gf/os/glog"
|
2017-12-07 14:57:16 +08:00
|
|
|
|
)
|
|
|
|
|
|
2018-04-27 22:12:11 +08:00
|
|
|
|
const (
|
2019-09-26 20:01:48 +08:00
|
|
|
|
gDEFAULT_HTTP_ADDR = ":80" // 默认HTTP监听地址
|
|
|
|
|
gDEFAULT_HTTPS_ADDR = ":443" // 默认HTTPS监听地址
|
|
|
|
|
URI_TYPE_DEFAULT = 0 // 服务注册时对象和方法名称转换为URI时,全部转为小写,单词以'-'连接符号连接
|
|
|
|
|
URI_TYPE_FULLNAME = 1 // 不处理名称,以原有名称构建成URI
|
|
|
|
|
URI_TYPE_ALLLOWER = 2 // 仅转为小写,单词间不使用连接符号
|
|
|
|
|
URI_TYPE_CAMEL = 3 // 采用驼峰命名方式
|
2018-04-27 22:12:11 +08:00
|
|
|
|
)
|
|
|
|
|
|
2019-11-07 16:40:34 +08:00
|
|
|
|
// LogHandler is the log handler function type.
|
2019-09-14 22:53:28 +08:00
|
|
|
|
type LogHandler func(r *Request, err ...error)
|
2018-09-14 13:02:13 +08:00
|
|
|
|
|
2019-11-07 16:40:34 +08:00
|
|
|
|
// HTTP Server configuration.
|
2017-12-07 14:57:16 +08:00
|
|
|
|
type ServerConfig struct {
|
2019-11-07 11:32:25 +08:00
|
|
|
|
Address string // Server listening address like ":port", multiple addresses separated using ','
|
2019-09-11 21:19:45 +08:00
|
|
|
|
HTTPSAddr string // HTTPS服务监听地址(支持多个地址,使用","号分隔)
|
|
|
|
|
HTTPSCertPath string // HTTPS证书文件路径
|
|
|
|
|
HTTPSKeyPath string // HTTPS签名文件路径
|
|
|
|
|
Handler http.Handler // 默认的处理函数
|
|
|
|
|
ReadTimeout time.Duration // 读取超时
|
|
|
|
|
WriteTimeout time.Duration // 写入超时
|
|
|
|
|
IdleTimeout time.Duration // 等待超时
|
|
|
|
|
MaxHeaderBytes int // 最大的header长度
|
2019-11-07 16:40:34 +08:00
|
|
|
|
TLSConfig *tls.Config // HTTPS证书配置
|
2019-09-11 21:19:45 +08:00
|
|
|
|
KeepAlive bool // 是否开启长连接
|
|
|
|
|
ServerAgent string // Server Agent
|
|
|
|
|
View *gview.View // 模板引擎对象
|
|
|
|
|
Rewrites map[string]string // URI Rewrite重写配置
|
|
|
|
|
IndexFiles []string // Static: 默认访问的文件列表
|
|
|
|
|
IndexFolder bool // Static: 如果访问目录是否显示目录列表
|
|
|
|
|
ServerRoot string // Static: 服务器服务的本地目录根路径(检索优先级比StaticPaths低)
|
|
|
|
|
SearchPaths []string // Static: 静态文件搜索目录(包含ServerRoot,按照优先级进行排序)
|
|
|
|
|
StaticPaths []staticPathItem // Static: 静态文件目录映射(按照优先级进行排序)
|
|
|
|
|
FileServerEnabled bool // Static: 是否允许静态文件服务(通过静态文件服务方法调用自动识别)
|
|
|
|
|
CookieMaxAge time.Duration // Cookie: 有效期
|
|
|
|
|
CookiePath string // Cookie: 有效Path(注意同时也会影响SessionID)
|
|
|
|
|
CookieDomain string // Cookie: 有效Domain(注意同时也会影响SessionID)
|
|
|
|
|
SessionMaxAge time.Duration // Session: 有效期
|
2019-10-29 16:45:42 +08:00
|
|
|
|
SessionIdName string // Session: SessionId.
|
2019-11-07 20:36:33 +08:00
|
|
|
|
SessionPath string // Session: Session Storage path for storing session files.
|
2019-10-29 16:45:42 +08:00
|
|
|
|
SessionStorage gsession.Storage // Session: Session Storage implementer.
|
2019-09-11 21:19:45 +08:00
|
|
|
|
DenyIps []string // Security: 不允许访问的ip列表,支持ip前缀过滤,如: 10 将不允许10开头的ip访问
|
|
|
|
|
AllowIps []string // Security: 仅允许访问的ip列表,支持ip前缀过滤,如: 10 将仅允许10开头的ip访问
|
|
|
|
|
DenyRoutes []string // Security: 不允许访问的路由规则列表
|
|
|
|
|
LogPath string // Logging: 存放日志的目录路径(默认为空,表示不写文件)
|
|
|
|
|
LogHandler LogHandler // Logging: 日志配置: 自定义日志处理回调方法(默认为空)
|
|
|
|
|
LogStdout bool // Logging: 是否打印日志到终端(默认开启)
|
2019-09-14 22:53:28 +08:00
|
|
|
|
ErrorStack bool // Logging: 当产生错误时打印调用链详细堆栈
|
2019-09-11 21:19:45 +08:00
|
|
|
|
ErrorLogEnabled bool // Logging: 是否开启error log(默认开启)
|
2019-11-07 16:40:34 +08:00
|
|
|
|
ErrorLogPattern string // Logging: Error log file pattern like: error-{Ymd}.log
|
2019-09-11 21:19:45 +08:00
|
|
|
|
AccessLogEnabled bool // Logging: 是否开启access log(默认关闭)
|
2019-11-07 16:40:34 +08:00
|
|
|
|
AccessLogPattern string // Logging: Error log file pattern like: access-{Ymd}.log
|
|
|
|
|
PProfEnabled bool // PProf: Enable PProf feature or not.
|
|
|
|
|
PProfPattern string // PProf: PProf pattern for router, it enables PProf feature if it's not empty.
|
2019-09-19 09:09:12 +08:00
|
|
|
|
FormParsingMemory int64 // Mess: 表单解析内存限制(byte)
|
2019-09-11 21:19:45 +08:00
|
|
|
|
NameToUriType int // Mess: 服务注册时对象和方法名称转换为URI时的规则
|
|
|
|
|
GzipContentTypes []string // Mess: 允许进行gzip压缩的文件类型
|
|
|
|
|
DumpRouteMap bool // Mess: 是否在程序启动时默认打印路由表信息
|
|
|
|
|
RouterCacheExpire int // Mess: 路由检索缓存过期时间(秒)
|
2017-12-07 14:57:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-11-24 11:55:57 +08:00
|
|
|
|
// 默认HTTP Server配置
|
2019-06-19 09:06:52 +08:00
|
|
|
|
var defaultServerConfig = ServerConfig{
|
2019-11-07 11:32:25 +08:00
|
|
|
|
Address: "",
|
2019-09-11 21:19:45 +08:00
|
|
|
|
HTTPSAddr: "",
|
|
|
|
|
Handler: nil,
|
|
|
|
|
ReadTimeout: 60 * time.Second,
|
|
|
|
|
WriteTimeout: 60 * time.Second,
|
|
|
|
|
IdleTimeout: 60 * time.Second,
|
|
|
|
|
MaxHeaderBytes: 1024,
|
|
|
|
|
KeepAlive: true,
|
|
|
|
|
IndexFiles: []string{"index.html", "index.htm"},
|
|
|
|
|
IndexFolder: false,
|
2019-11-07 16:40:34 +08:00
|
|
|
|
ServerAgent: "GF HTTP Server",
|
2019-09-11 21:19:45 +08:00
|
|
|
|
ServerRoot: "",
|
|
|
|
|
StaticPaths: make([]staticPathItem, 0),
|
|
|
|
|
FileServerEnabled: false,
|
|
|
|
|
CookieMaxAge: time.Hour * 24 * 365,
|
|
|
|
|
CookiePath: "/",
|
|
|
|
|
CookieDomain: "",
|
|
|
|
|
SessionMaxAge: time.Hour * 24,
|
|
|
|
|
SessionIdName: "gfsessionid",
|
2019-11-07 20:36:33 +08:00
|
|
|
|
SessionPath: gsession.DefaultStorageFilePath,
|
2019-09-11 21:19:45 +08:00
|
|
|
|
LogStdout: true,
|
2019-09-14 22:53:28 +08:00
|
|
|
|
ErrorStack: true,
|
2019-09-11 21:19:45 +08:00
|
|
|
|
ErrorLogEnabled: true,
|
2019-11-07 16:40:34 +08:00
|
|
|
|
ErrorLogPattern: "error-{Ymd}.log",
|
2019-09-11 21:19:45 +08:00
|
|
|
|
AccessLogEnabled: false,
|
2019-11-07 16:40:34 +08:00
|
|
|
|
AccessLogPattern: "access-{Ymd}.log",
|
2019-09-11 21:19:45 +08:00
|
|
|
|
DumpRouteMap: true,
|
2019-09-19 09:09:12 +08:00
|
|
|
|
FormParsingMemory: 1024 * 1024 * 1024,
|
2019-09-11 21:19:45 +08:00
|
|
|
|
RouterCacheExpire: 60,
|
|
|
|
|
Rewrites: make(map[string]string),
|
2017-12-07 14:57:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 获取默认的http server设置
|
2018-09-14 13:02:13 +08:00
|
|
|
|
func Config() ServerConfig {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
return defaultServerConfig
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-13 20:49:16 +08:00
|
|
|
|
// 通过Map创建Config配置对象,Map没有传递的属性将会使用模块的默认值
|
2019-11-07 11:32:25 +08:00
|
|
|
|
func ConfigFromMap(m map[string]interface{}) (ServerConfig, error) {
|
2019-09-13 20:49:16 +08:00
|
|
|
|
config := defaultServerConfig
|
2019-11-06 20:23:41 +08:00
|
|
|
|
if err := gconv.Struct(m, &config); err != nil {
|
2019-11-07 11:32:25 +08:00
|
|
|
|
return config, err
|
2019-11-06 20:23:41 +08:00
|
|
|
|
}
|
2019-11-07 11:32:25 +08:00
|
|
|
|
return config, nil
|
2019-09-13 20:49:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// http server setting设置。
|
2018-08-12 12:22:02 +08:00
|
|
|
|
// 注意使用该方法进行http server配置时,需要配置所有的配置项,否则没有配置的属性将会默认变量为空
|
2019-09-26 20:01:48 +08:00
|
|
|
|
func (s *Server) SetConfig(c ServerConfig) error {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
if c.Handler == nil {
|
|
|
|
|
c.Handler = http.HandlerFunc(s.defaultHttpHandle)
|
|
|
|
|
}
|
|
|
|
|
s.config = c
|
2019-11-07 16:40:34 +08:00
|
|
|
|
// Logging.
|
2019-06-19 09:06:52 +08:00
|
|
|
|
if c.LogPath != "" {
|
2019-09-26 20:01:48 +08:00
|
|
|
|
return s.logger.SetPath(c.LogPath)
|
2019-06-19 09:06:52 +08:00
|
|
|
|
}
|
2019-11-07 16:40:34 +08:00
|
|
|
|
// HTTPS.
|
|
|
|
|
if c.TLSConfig == nil && c.HTTPSCertPath != "" {
|
|
|
|
|
s.EnableHTTPS(c.HTTPSCertPath, c.HTTPSKeyPath)
|
|
|
|
|
}
|
2019-09-26 20:01:48 +08:00
|
|
|
|
return nil
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-09-13 20:49:16 +08:00
|
|
|
|
// 通过map设置http server setting。
|
|
|
|
|
// 注意使用该方法进行http server配置时,需要配置所有的配置项,否则没有配置的属性将会默认变量为空
|
2019-11-07 11:32:25 +08:00
|
|
|
|
func (s *Server) SetConfigWithMap(m map[string]interface{}) error {
|
|
|
|
|
config, err := ConfigFromMap(m)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
return s.SetConfig(config)
|
2019-09-13 20:49:16 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-12 12:22:02 +08:00
|
|
|
|
// 设置http server参数 - Addr
|
2019-09-24 20:19:18 +08:00
|
|
|
|
func (s *Server) SetAddr(address string) {
|
2019-11-07 11:32:25 +08:00
|
|
|
|
s.config.Address = address
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置http server参数 - Port
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (s *Server) SetPort(port ...int) {
|
|
|
|
|
if len(port) > 0 {
|
2019-11-07 11:32:25 +08:00
|
|
|
|
s.config.Address = ""
|
2019-06-19 09:06:52 +08:00
|
|
|
|
for _, v := range port {
|
2019-11-07 11:32:25 +08:00
|
|
|
|
if len(s.config.Address) > 0 {
|
|
|
|
|
s.config.Address += ","
|
2019-06-19 09:06:52 +08:00
|
|
|
|
}
|
2019-11-07 11:32:25 +08:00
|
|
|
|
s.config.Address += ":" + strconv.Itoa(v)
|
2019-06-19 09:06:52 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置http server参数 - HTTPS Addr
|
2019-09-24 20:19:18 +08:00
|
|
|
|
func (s *Server) SetHTTPSAddr(address string) {
|
|
|
|
|
s.config.HTTPSAddr = address
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置http server参数 - HTTPS Port
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (s *Server) SetHTTPSPort(port ...int) {
|
|
|
|
|
if len(port) > 0 {
|
|
|
|
|
s.config.HTTPSAddr = ""
|
|
|
|
|
for _, v := range port {
|
|
|
|
|
if len(s.config.HTTPSAddr) > 0 {
|
|
|
|
|
s.config.HTTPSAddr += ","
|
|
|
|
|
}
|
|
|
|
|
s.config.HTTPSAddr += ":" + strconv.Itoa(v)
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-19 17:48:37 +08:00
|
|
|
|
// 开启HTTPS支持,但是必须提供Cert和Key文件,tlsConfig为可选项
|
2019-11-07 16:40:34 +08:00
|
|
|
|
func (s *Server) EnableHTTPS(certFile, keyFile string, tlsConfig ...*tls.Config) {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
certFileRealPath := gfile.RealPath(certFile)
|
|
|
|
|
if certFileRealPath == "" {
|
|
|
|
|
certFileRealPath = gfile.RealPath(gfile.Pwd() + gfile.Separator + certFile)
|
|
|
|
|
if certFileRealPath == "" {
|
|
|
|
|
certFileRealPath = gfile.RealPath(gfile.MainPkgPath() + gfile.Separator + certFile)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if certFileRealPath == "" {
|
|
|
|
|
glog.Fatal(fmt.Sprintf(`[ghttp] EnableHTTPS failed: certFile "%s" does not exist`, certFile))
|
|
|
|
|
}
|
|
|
|
|
keyFileRealPath := gfile.RealPath(keyFile)
|
|
|
|
|
if keyFileRealPath == "" {
|
|
|
|
|
keyFileRealPath = gfile.RealPath(gfile.Pwd() + gfile.Separator + keyFile)
|
|
|
|
|
if keyFileRealPath == "" {
|
|
|
|
|
keyFileRealPath = gfile.RealPath(gfile.MainPkgPath() + gfile.Separator + keyFile)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if keyFileRealPath == "" {
|
|
|
|
|
glog.Fatal(fmt.Sprintf(`[ghttp] EnableHTTPS failed: keyFile "%s" does not exist`, keyFile))
|
|
|
|
|
}
|
|
|
|
|
s.config.HTTPSCertPath = certFileRealPath
|
|
|
|
|
s.config.HTTPSKeyPath = keyFileRealPath
|
|
|
|
|
if len(tlsConfig) > 0 {
|
|
|
|
|
s.config.TLSConfig = tlsConfig[0]
|
|
|
|
|
}
|
2019-03-19 17:48:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置TLS配置对象
|
2019-11-07 16:40:34 +08:00
|
|
|
|
func (s *Server) SetTLSConfig(tlsConfig *tls.Config) {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
s.config.TLSConfig = tlsConfig
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置http server参数 - ReadTimeout
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (s *Server) SetReadTimeout(t time.Duration) {
|
|
|
|
|
s.config.ReadTimeout = t
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置http server参数 - WriteTimeout
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (s *Server) SetWriteTimeout(t time.Duration) {
|
|
|
|
|
s.config.WriteTimeout = t
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置http server参数 - IdleTimeout
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (s *Server) SetIdleTimeout(t time.Duration) {
|
|
|
|
|
s.config.IdleTimeout = t
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置http server参数 - MaxHeaderBytes
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (s *Server) SetMaxHeaderBytes(b int) {
|
|
|
|
|
s.config.MaxHeaderBytes = b
|
2018-08-12 12:22:02 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 设置http server参数 - ServerAgent
|
2019-06-19 09:06:52 +08:00
|
|
|
|
func (s *Server) SetServerAgent(agent string) {
|
|
|
|
|
s.config.ServerAgent = agent
|
2018-11-23 09:20:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-02 22:19:52 +08:00
|
|
|
|
// 设置KeepAlive
|
|
|
|
|
func (s *Server) SetKeepAlive(enabled bool) {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
s.config.KeepAlive = enabled
|
2019-06-02 22:19:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
2019-08-16 00:29:14 +08:00
|
|
|
|
// 设置模板引擎对象
|
|
|
|
|
func (s *Server) SetView(view *gview.View) {
|
|
|
|
|
s.config.View = view
|
|
|
|
|
}
|
|
|
|
|
|
2018-11-28 20:19:28 +08:00
|
|
|
|
// 获取WebServer名称
|
2018-08-12 12:22:02 +08:00
|
|
|
|
func (s *Server) GetName() string {
|
2019-06-19 09:06:52 +08:00
|
|
|
|
return s.name
|
|
|
|
|
}
|