WebServer改进

This commit is contained in:
John
2018-11-28 20:19:28 +08:00
parent 8304769953
commit aee266eea0
19 changed files with 130 additions and 104 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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、动态队列初始化速度快

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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标识引导客户端跳转到来源页面

View File

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

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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

View 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
}

View File

@ -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) {
// 如果已经添加则不再添加

View File

@ -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)