mirror of
https://gitee.com/johng/gf
synced 2026-07-07 14:25:17 +08:00
WebServer改进
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package garray provides kinds of concurrent-safe(alternative) arrays.
|
||||
// 并发安全的数组.
|
||||
package garray
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package gchan provides graceful operations for channel.
|
||||
// 优雅的Channel操作.
|
||||
package gchan
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
//
|
||||
|
||||
// Package glist provides a concurrent-safe(alternative) doubly linked list.
|
||||
// 并发安全的双向链表.
|
||||
package glist
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package gmap provides kinds of concurrent-safe(alternative) maps.
|
||||
// 并发安全的哈希MAP.
|
||||
package gmap
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package gpool provides a object-reusable concurrent-safe pool.
|
||||
// 对象复用池.
|
||||
package gpool
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package gqueue provides a dynamic/static concurrent-safe(alternative) queue.
|
||||
// 并发安全的动态队列.
|
||||
// 特点:
|
||||
// 1、动态队列初始化速度快;
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package gring provides a concurrent-safe(alternative) ring(circular lists).
|
||||
// 并发安全的环.
|
||||
package gring
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package gset provides kinds of concurrent-safe(alternative) sets.
|
||||
// 并发安全的集合SET.
|
||||
package gset
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package gtype provides kinds of concurrent-safe basic-types.
|
||||
// 并发安全的基本类型.
|
||||
package gtype
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// Package gvar provides a universal variable type.
|
||||
// 通用动态变量.
|
||||
package gvar
|
||||
|
||||
|
||||
@ -195,6 +195,7 @@ func (r *Response) ServeFileDownload(path string, name...string) {
|
||||
func (r *Response) RedirectTo(location string) {
|
||||
r.Header().Set("Location", location)
|
||||
r.WriteHeader(http.StatusFound)
|
||||
r.request.Exit()
|
||||
}
|
||||
|
||||
// 返回location标识,引导客户端跳转到来源页面
|
||||
|
||||
@ -38,7 +38,6 @@ type (
|
||||
Server struct {
|
||||
// 基本属性变量
|
||||
name string // 服务名称,方便识别
|
||||
paths *gspath.SPath // 静态文件检索对象(类似nginx tryfile功能)
|
||||
config ServerConfig // 配置对象
|
||||
servers []*gracefulServer // 底层http.Server列表
|
||||
methodsMap map[string]struct{} // 所有支持的HTTP Method(初始化时自动填充)
|
||||
@ -179,7 +178,6 @@ func GetServer(name...interface{}) (*Server) {
|
||||
}
|
||||
s := &Server {
|
||||
name : sname,
|
||||
paths : gspath.New(),
|
||||
servers : make([]*gracefulServer, 0),
|
||||
methodsMap : make(map[string]struct{}),
|
||||
statusHandlerMap : make(map[string]HandlerFunc),
|
||||
|
||||
@ -3,17 +3,14 @@
|
||||
// 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,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
// 配置管理数据结构定义.
|
||||
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"time"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -36,49 +33,51 @@ type LogHandler func(r *Request, error ... interface{})
|
||||
// HTTP Server 设置结构体,静态配置
|
||||
type ServerConfig struct {
|
||||
// 底层http对象配置
|
||||
Addr string // 监听IP和端口,监听本地所有IP使用":端口"(支持多个地址,使用","号分隔)
|
||||
HTTPSAddr string // HTTPS服务监听地址(支持多个地址,使用","号分隔)
|
||||
HTTPSCertPath string // HTTPS证书文件路径
|
||||
HTTPSKeyPath string // HTTPS签名文件路径
|
||||
Handler http.Handler // 默认的处理函数
|
||||
ReadTimeout time.Duration // 读取超时
|
||||
WriteTimeout time.Duration // 写入超时
|
||||
IdleTimeout time.Duration // 等待超时
|
||||
MaxHeaderBytes int // 最大的header长度
|
||||
Addr string // 监听IP和端口,监听本地所有IP使用":端口"(支持多个地址,使用","号分隔)
|
||||
HTTPSAddr string // HTTPS服务监听地址(支持多个地址,使用","号分隔)
|
||||
HTTPSCertPath string // HTTPS证书文件路径
|
||||
HTTPSKeyPath string // HTTPS签名文件路径
|
||||
Handler http.Handler // 默认的处理函数
|
||||
ReadTimeout time.Duration // 读取超时
|
||||
WriteTimeout time.Duration // 写入超时
|
||||
IdleTimeout time.Duration // 等待超时
|
||||
MaxHeaderBytes int // 最大的header长度
|
||||
|
||||
// 静态文件配置
|
||||
IndexFiles []string // 默认访问的文件列表
|
||||
IndexFolder bool // 如果访问目录是否显示目录列表
|
||||
ServerAgent string // server agent
|
||||
ServerRoot string // 服务器服务的本地目录根路径
|
||||
FileServerEnabled bool // 是否允许静态文件服务(默认开启)
|
||||
IndexFiles []string // 默认访问的文件列表
|
||||
IndexFolder bool // 如果访问目录是否显示目录列表
|
||||
ServerAgent string // Server Agent
|
||||
ServerRoot string // 服务器服务的本地目录根路径(检索优先级比StaticPaths低)
|
||||
SearchPaths []string // 静态文件搜索目录(包含ServerRoot,按照优先级进行排序)
|
||||
StaticPaths []map[string]string // 静态文件目录映射(按照优先级进行排序)
|
||||
FileServerEnabled bool // 是否允许静态文件服务(总开关,默认开启)
|
||||
|
||||
// COOKIE
|
||||
CookieMaxAge int // Cookie有效期
|
||||
CookiePath string // Cookie有效Path(注意同时也会影响SessionID)
|
||||
CookieDomain string // Cookie有效Domain(注意同时也会影响SessionID)
|
||||
CookieMaxAge int // Cookie有效期
|
||||
CookiePath string // Cookie有效Path(注意同时也会影响SessionID)
|
||||
CookieDomain string // Cookie有效Domain(注意同时也会影响SessionID)
|
||||
|
||||
// SESSION
|
||||
SessionMaxAge int // Session有效期
|
||||
SessionIdName string // SessionId名称
|
||||
SessionMaxAge int // Session有效期
|
||||
SessionIdName string // SessionId名称
|
||||
|
||||
// ip访问控制
|
||||
DenyIps []string // 不允许访问的ip列表,支持ip前缀过滤,如: 10 将不允许10开头的ip访问
|
||||
AllowIps []string // 仅允许访问的ip列表,支持ip前缀过滤,如: 10 将仅允许10开头的ip访问
|
||||
DenyIps []string // 不允许访问的ip列表,支持ip前缀过滤,如: 10 将不允许10开头的ip访问
|
||||
AllowIps []string // 仅允许访问的ip列表,支持ip前缀过滤,如: 10 将仅允许10开头的ip访问
|
||||
// 路由访问控制
|
||||
DenyRoutes []string // 不允许访问的路由规则列表
|
||||
DenyRoutes []string // 不允许访问的路由规则列表
|
||||
|
||||
// 日志配置
|
||||
LogPath string // 存放日志的目录路径
|
||||
LogHandler LogHandler // 自定义日志处理回调方法
|
||||
ErrorLogEnabled bool // 是否开启error log
|
||||
AccessLogEnabled bool // 是否开启access log
|
||||
LogPath string // 存放日志的目录路径
|
||||
LogHandler LogHandler // 自定义日志处理回调方法
|
||||
ErrorLogEnabled bool // 是否开启error log
|
||||
AccessLogEnabled bool // 是否开启access log
|
||||
|
||||
// 其他设置
|
||||
NameToUriType int // 服务注册时对象和方法名称转换为URI时的规则
|
||||
GzipContentTypes []string // 允许进行gzip压缩的文件类型
|
||||
DumpRouteMap bool // 是否在程序启动时默认打印路由表信息
|
||||
RouterCacheExpire int // 路由检索缓存过期时间(秒)
|
||||
NameToUriType int // 服务注册时对象和方法名称转换为URI时的规则
|
||||
GzipContentTypes []string // 允许进行gzip压缩的文件类型
|
||||
DumpRouteMap bool // 是否在程序启动时默认打印路由表信息
|
||||
RouterCacheExpire int // 路由检索缓存过期时间(秒)
|
||||
}
|
||||
|
||||
// 默认HTTP Server配置
|
||||
@ -90,10 +89,12 @@ var defaultServerConfig = ServerConfig {
|
||||
WriteTimeout : 60 * time.Second,
|
||||
IdleTimeout : 60 * time.Second,
|
||||
MaxHeaderBytes : 1024,
|
||||
|
||||
IndexFiles : []string{"index.html", "index.htm"},
|
||||
IndexFolder : false,
|
||||
ServerAgent : "gf",
|
||||
ServerRoot : "",
|
||||
StaticPaths : make([]map[string]string, 0),
|
||||
FileServerEnabled : true,
|
||||
|
||||
CookieMaxAge : gDEFAULT_COOKIE_MAX_AGE,
|
||||
@ -232,25 +233,6 @@ func (s *Server)SetMaxHeaderBytes(b int) {
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - IndexFiles,默认展示文件,如:index.html, index.htm
|
||||
func (s *Server)SetIndexFiles(index []string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
|
||||
return
|
||||
}
|
||||
s.config.IndexFiles = index
|
||||
}
|
||||
|
||||
// 允许展示访问目录的文件列表
|
||||
func (s *Server)SetIndexFolder(index bool) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
|
||||
return
|
||||
}
|
||||
s.config.IndexFolder = index
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - ServerAgent
|
||||
func (s *Server)SetServerAgent(agent string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
@ -258,30 +240,6 @@ func (s *Server)SetServerAgent(agent string) {
|
||||
return
|
||||
}
|
||||
s.config.ServerAgent = agent
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - ServerRoot
|
||||
func (s *Server)SetServerRoot(root string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
|
||||
return
|
||||
}
|
||||
// RealPath的作用除了校验地址正确性以外,还转换分隔符号为当前系统正确的文件分隔符号
|
||||
path := gfile.RealPath(root)
|
||||
if path == "" {
|
||||
glog.Error("invalid root path \"" + root + "\"")
|
||||
}
|
||||
s.config.ServerRoot = strings.TrimRight(path, gfile.Separator)
|
||||
}
|
||||
|
||||
// 是否开启/关闭静态文件服务,当关闭时仅提供动态接口服务,路由性能会得到一定提升
|
||||
func (s *Server) SetFileServerEnabled(enabled bool) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
|
||||
return
|
||||
}
|
||||
s.config.FileServerEnabled = enabled
|
||||
}
|
||||
|
||||
func (s *Server) SetDenyIps(ips []string) {
|
||||
@ -343,18 +301,7 @@ func (s *Server) SetRouterCacheExpire(expire int) {
|
||||
s.config.RouterCacheExpire = expire
|
||||
}
|
||||
|
||||
// 添加静态文件搜索目录,必须给定目录的绝对路径
|
||||
func (s *Server) AddSearchPath(path string) error {
|
||||
if rp, err := s.paths.Add(path); err != nil {
|
||||
glog.Error("ghttp.AddSearchPath failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
glog.Debug("ghttp.AddSearchPath:", rp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取
|
||||
// 获取WebServer名称
|
||||
func (s *Server) GetName() string {
|
||||
return s.name
|
||||
}
|
||||
@ -3,7 +3,6 @@
|
||||
// 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,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
// 配置管理数据结构定义.
|
||||
|
||||
package ghttp
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
// 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,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
// 配置管理数据结构定义.
|
||||
|
||||
package ghttp
|
||||
|
||||
|
||||
@ -3,7 +3,6 @@
|
||||
// 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,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
// 配置管理数据结构定义.
|
||||
|
||||
package ghttp
|
||||
|
||||
|
||||
79
g/net/ghttp/ghttp_server_config_static.go
Normal file
79
g/net/ghttp/ghttp_server_config_static.go
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
|
||||
//
|
||||
// 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,
|
||||
// You can obtain one at https://gitee.com/johng/gf.
|
||||
|
||||
// 静态文件搜索优先级: ServerPaths > ServerRoot > SearchPath
|
||||
|
||||
package ghttp
|
||||
|
||||
import (
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 设置http server参数 - IndexFiles,默认展示文件,如:index.html, index.htm
|
||||
func (s *Server)SetIndexFiles(index []string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
|
||||
return
|
||||
}
|
||||
s.config.IndexFiles = index
|
||||
}
|
||||
|
||||
// 允许展示访问目录的文件列表
|
||||
func (s *Server)SetIndexFolder(enabled bool) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
|
||||
return
|
||||
}
|
||||
s.config.IndexFolder = enabled
|
||||
}
|
||||
|
||||
// 是否开启/关闭静态文件服务,当关闭时仅提供动态接口服务,路由性能会得到一定提升
|
||||
func (s *Server) SetFileServerEnabled(enabled bool) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
|
||||
return
|
||||
}
|
||||
s.config.FileServerEnabled = enabled
|
||||
}
|
||||
|
||||
// 设置http server参数 - ServerRoot
|
||||
func (s *Server)SetServerRoot(root string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error(gCHANGE_CONFIG_WHILE_RUNNING_ERROR)
|
||||
return
|
||||
}
|
||||
// RealPath的作用除了校验地址正确性以外,还转换分隔符号为当前系统正确的文件分隔符号
|
||||
path := gfile.RealPath(root)
|
||||
if path == "" {
|
||||
glog.Error("invalid root path \"" + root + "\"")
|
||||
}
|
||||
s.config.ServerRoot = strings.TrimRight(path, gfile.Separator)
|
||||
}
|
||||
|
||||
// 添加静态文件搜索目录,必须给定目录的绝对路径
|
||||
func (s *Server) AddSearchPath(path string) error {
|
||||
if rp, err := s.paths.Add(path); err != nil {
|
||||
glog.Error("[ghttp] AddSearchPath failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
glog.Debug("[ghttp] AddSearchPath:", rp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 添加URI与静态目录的映射
|
||||
func (s *Server) AddStaticPath(prefix string, path string) error {
|
||||
if rp, err := s.paths.Add(path); err != nil {
|
||||
glog.Error("[ghttp] AddSearchPath failed:", err.Error())
|
||||
return err
|
||||
} else {
|
||||
glog.Debug("[ghttp] AddSearchPath:", rp)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -29,8 +29,8 @@ type SPath struct {
|
||||
|
||||
// 文件搜索缓存项
|
||||
type SPathCacheItem struct {
|
||||
path string // 文件/目录绝对路径
|
||||
isDir bool // 是否目录
|
||||
path string // 文件/目录绝对路径
|
||||
isDir bool // 是否目录
|
||||
}
|
||||
|
||||
// 创建一个搜索对象
|
||||
@ -53,9 +53,6 @@ func (sp *SPath) Set(path string) (realPath string, err error) {
|
||||
if realPath == "" {
|
||||
return realPath, errors.New(fmt.Sprintf(`path "%s" does not exist`, path))
|
||||
}
|
||||
if realPath == "" {
|
||||
return realPath, errors.New("invalid path:" + path)
|
||||
}
|
||||
// 设置的搜索路径必须为目录
|
||||
if gfile.IsDir(realPath) {
|
||||
realPath = strings.TrimRight(realPath, gfile.Separator)
|
||||
@ -87,9 +84,6 @@ func (sp *SPath) Add(path string) (realPath string, err error) {
|
||||
if realPath == "" {
|
||||
return realPath, errors.New(fmt.Sprintf(`path "%s" does not exist`, path))
|
||||
}
|
||||
if realPath == "" {
|
||||
return realPath, errors.New("invalid path:" + path)
|
||||
}
|
||||
// 添加的搜索路径必须为目录
|
||||
if gfile.IsDir(realPath) {
|
||||
// 如果已经添加则不再添加
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// 验证 map 的delete方法是否并发安全
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -7,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// 验证 map 的delete方法是否并发安全
|
||||
func main() {
|
||||
// 创建一个初始化的map
|
||||
m := make(map[int]int)
|
||||
|
||||
Reference in New Issue
Block a user