mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
改进
This commit is contained in:
2
TODO
2
TODO
@ -15,6 +15,8 @@ map转struct增加对tag的支持;
|
||||
gcache检查在i386下的int64->int转换问题;
|
||||
gfsnotify增加对于目录的监控;
|
||||
orm增加sqlite对Save方法的支持(去掉触发器语句);
|
||||
ghttp.Server的Cookie及Session锁机制优化(去掉map锁机制);
|
||||
ghttp.Server增加Ip访问控制功能(DenyIps&AllowIps);
|
||||
|
||||
DONE:
|
||||
1. gconv完善针对不同类型的判断,例如:尽量减少sprintf("%v", xxx)来执行string类型的转换;
|
||||
|
||||
@ -70,7 +70,7 @@ func (p *Pool) Get() (interface{}, error) {
|
||||
for !p.closed.Val() {
|
||||
if r := p.list.PopFront(); r != nil {
|
||||
f := r.(*poolItem)
|
||||
if f.expire > gtime.Millisecond() {
|
||||
if f.expire == 0 || f.expire > gtime.Millisecond() {
|
||||
return f.value, nil
|
||||
}
|
||||
} else {
|
||||
@ -99,7 +99,7 @@ func (p *Pool) expireCheckingLoop() {
|
||||
for {
|
||||
if r := p.list.PopFront(); r != nil {
|
||||
item := r.(*poolItem)
|
||||
if item.expire > gtime.Millisecond() {
|
||||
if item.expire == 0 || item.expire > gtime.Millisecond() {
|
||||
p.list.PushFront(item)
|
||||
break
|
||||
}
|
||||
|
||||
@ -22,16 +22,22 @@ import (
|
||||
"gitee.com/johng/gf/g/container/gtype"
|
||||
"gitee.com/johng/gf/g/container/gqueue"
|
||||
"gitee.com/johng/gf/g/os/gspath"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"gitee.com/johng/gf/g/os/genv"
|
||||
"github.com/gorilla/websocket"
|
||||
"gitee.com/johng/gf/g/os/gtime"
|
||||
"time"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
)
|
||||
|
||||
const (
|
||||
SERVER_STATUS_STOPPED = 0 // Server状态:停止
|
||||
SERVER_STATUS_RUNNING = 1 // Server状态:运行
|
||||
HOOK_BEFORE_SERVE = "BeforeServe"
|
||||
HOOK_AFTER_SERVE = "AfterServe"
|
||||
HOOK_BEFORE_OUTPUT = "BeforeOutput"
|
||||
HOOK_AFTER_OUTPUT = "AfterOutput"
|
||||
HOOK_BEFORE_CLOSE = "BeforeClose"
|
||||
HOOK_AFTER_CLOSE = "AfterClose"
|
||||
)
|
||||
const (
|
||||
gHTTP_METHODS = "GET,PUT,POST,DELETE,PATCH,HEAD,CONNECT,OPTIONS,TRACE"
|
||||
@ -208,8 +214,14 @@ func GetServer(name...interface{}) (*Server) {
|
||||
// 作为守护协程异步执行(当同一进程中存在多个Web Server时,需要采用这种方式执行)
|
||||
// 需要结合Wait方式一起使用
|
||||
func (s *Server) Start() error {
|
||||
// 服务进程初始化,只会初始化一次
|
||||
serverProcInit()
|
||||
|
||||
// 当前Web Server状态判断
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server is already running")
|
||||
}
|
||||
|
||||
// 如果设置了静态文件目录,那么严格按照静态文件目录进行检索
|
||||
// 否则,默认使用当前可执行文件目录,并且如果是开发环境,默认也会添加main包的源码目录路径做为二级检索
|
||||
if s.config.ServerRoot != "" {
|
||||
@ -221,13 +233,19 @@ func (s *Server) Start() error {
|
||||
}
|
||||
}
|
||||
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server is already running")
|
||||
}
|
||||
// 底层http server配置
|
||||
if s.config.Handler == nil {
|
||||
s.config.Handler = http.HandlerFunc(s.defaultHttpHandle)
|
||||
}
|
||||
// 不允许访问的路由注册
|
||||
if s.config.DenyRoutes != nil {
|
||||
for _, v := range s.config.DenyRoutes {
|
||||
s.BindHookHandler(v, HOOK_BEFORE_SERVE, func(r *Request) {
|
||||
r.Response.WriteStatus(403)
|
||||
r.Exit()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 启动http server
|
||||
reloaded := false
|
||||
|
||||
@ -9,11 +9,11 @@ package ghttp
|
||||
|
||||
import (
|
||||
"time"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
"strings"
|
||||
"gitee.com/johng/gf/g/os/glog"
|
||||
"gitee.com/johng/gf/g/os/gfile"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -28,21 +28,20 @@ const (
|
||||
// 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 // 服务器服务的本地目录根路径
|
||||
|
||||
IndexFiles []string // 默认访问的文件列表
|
||||
IndexFolder bool // 如果访问目录是否显示目录列表
|
||||
ServerAgent string // server agent
|
||||
ServerRoot string // 服务器服务的本地目录根路径
|
||||
// 日志配置
|
||||
LogPath string // 存放日志的目录路径
|
||||
LogHandler func(r *Request, error ... interface{}) // 自定义日志处理回调方法
|
||||
@ -55,6 +54,11 @@ type ServerConfig struct {
|
||||
SessionIdName string // SessionId名称
|
||||
// 其他设置
|
||||
NameToUriType int // 服务注册时对象和方法名称转换为URI时的规则
|
||||
// ip访问控制
|
||||
DenyIps []string // 不允许访问的ip列表,支持ip前缀过滤,如: 10 将不允许10开头的ip访问
|
||||
AllowIps []string // 仅允许访问的ip列表,支持ip前缀过滤,如: 10 将仅允许10开头的ip访问
|
||||
// 路由访问控制
|
||||
DenyRoutes []string // 不允许访问的路由规则列表
|
||||
}
|
||||
|
||||
// 默认HTTP Server
|
||||
@ -85,9 +89,9 @@ func DefaultSetting() ServerConfig {
|
||||
|
||||
// http server setting设置
|
||||
// 注意使用该方法进行http server配置时,需要配置所有的配置项,否则没有配置的属性将会默认变量为空
|
||||
func (s *Server)SetConfig(c ServerConfig) error {
|
||||
func (s *Server)SetConfig(c ServerConfig) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
if c.Handler == nil {
|
||||
c.Handler = http.HandlerFunc(s.defaultHttpHandle)
|
||||
@ -120,22 +124,21 @@ func (s *Server)SetConfig(c ServerConfig) error {
|
||||
s.SetSessionIdName(c.SessionIdName)
|
||||
}
|
||||
s.SetNameToUriType(c.NameToUriType)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - Addr
|
||||
func (s *Server)SetAddr(addr string) error {
|
||||
func (s *Server)SetAddr(addr string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.Addr = addr
|
||||
return nil
|
||||
}
|
||||
|
||||
// 设置http server参数 - Port
|
||||
func (s *Server)SetPort(port...int) error {
|
||||
func (s *Server)SetPort(port...int) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("config cannot be changed while running")
|
||||
}
|
||||
if len(port) > 0 {
|
||||
s.config.Addr = ""
|
||||
@ -146,22 +149,21 @@ func (s *Server)SetPort(port...int) error {
|
||||
s.config.Addr += ":" + strconv.Itoa(v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 设置http server参数 - HTTPS Addr
|
||||
func (s *Server)SetHTTPSAddr(addr string) error {
|
||||
func (s *Server)SetHTTPSAddr(addr string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.HTTPSAddr = addr
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - HTTPS Port
|
||||
func (s *Server)SetHTTPSPort(port...int) error {
|
||||
func (s *Server)SetHTTPSPort(port...int) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
if len(port) > 0 {
|
||||
s.config.HTTPSAddr = ""
|
||||
@ -172,94 +174,113 @@ func (s *Server)SetHTTPSPort(port...int) error {
|
||||
s.config.HTTPSAddr += ":" + strconv.Itoa(v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 开启HTTPS支持,但是必须提供Cert和Key文件
|
||||
func (s *Server)EnableHTTPS(certFile, keyFile string) error {
|
||||
func (s *Server)EnableHTTPS(certFile, keyFile string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.HTTPSCertPath = certFile
|
||||
s.config.HTTPSKeyPath = keyFile
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - ReadTimeout
|
||||
func (s *Server)SetReadTimeout(t time.Duration) error {
|
||||
func (s *Server)SetReadTimeout(t time.Duration) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.ReadTimeout = t
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - WriteTimeout
|
||||
func (s *Server)SetWriteTimeout(t time.Duration) error {
|
||||
func (s *Server)SetWriteTimeout(t time.Duration) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.WriteTimeout = t
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - IdleTimeout
|
||||
func (s *Server)SetIdleTimeout(t time.Duration) error {
|
||||
func (s *Server)SetIdleTimeout(t time.Duration) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.IdleTimeout = t
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - MaxHeaderBytes
|
||||
func (s *Server)SetMaxHeaderBytes(b int) error {
|
||||
func (s *Server)SetMaxHeaderBytes(b int) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.MaxHeaderBytes = b
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - IndexFiles,默认展示文件,如:index.html, index.htm
|
||||
func (s *Server)SetIndexFiles(index []string) error {
|
||||
func (s *Server)SetIndexFiles(index []string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.IndexFiles = index
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 允许展示访问目录的文件列表
|
||||
func (s *Server)SetIndexFolder(index bool) error {
|
||||
func (s *Server)SetIndexFolder(index bool) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.IndexFolder = index
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - ServerAgent
|
||||
func (s *Server)SetServerAgent(agent string) error {
|
||||
func (s *Server)SetServerAgent(agent string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.ServerAgent = agent
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// 设置http server参数 - ServerRoot
|
||||
func (s *Server)SetServerRoot(root string) error {
|
||||
func (s *Server)SetServerRoot(root string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
return errors.New("server config cannot be changed while running")
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
// RealPath的作用除了校验地址正确性以外,还转换分隔符号为当前系统正确的文件分隔符号
|
||||
path := gfile.RealPath(root)
|
||||
if path == "" {
|
||||
return errors.New("invalid root path \"" + root + "\"")
|
||||
glog.Error("invalid root path \"" + root + "\"")
|
||||
}
|
||||
s.config.ServerRoot = strings.TrimRight(path, string(gfile.Separator))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) SetDenyIps(ips []string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.DenyIps = ips
|
||||
}
|
||||
|
||||
func (s *Server) SetAllowIps(ips []string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.AllowIps = ips
|
||||
}
|
||||
|
||||
func (s *Server) SetDenyRoutes(routes []string) {
|
||||
if s.Status() == SERVER_STATUS_RUNNING {
|
||||
glog.Error("cannot be changed while running")
|
||||
}
|
||||
s.config.DenyRoutes = routes
|
||||
}
|
||||
|
||||
// 设置http server参数 - CookieMaxAge
|
||||
@ -278,20 +299,19 @@ func (s *Server)SetSessionIdName(name string) {
|
||||
}
|
||||
|
||||
// 设置日志目录
|
||||
func (s *Server)SetLogPath(path string) error {
|
||||
func (s *Server)SetLogPath(path string) {
|
||||
if len(path) == 0 {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
errorLogPath := strings.TrimRight(path, gfile.Separator) + gfile.Separator + "error"
|
||||
accessLogPath := strings.TrimRight(path, gfile.Separator) + gfile.Separator + "access"
|
||||
if err := s.accessLogger.SetPath(accessLogPath); err != nil {
|
||||
return err
|
||||
glog.Error(err)
|
||||
}
|
||||
if err := s.errorLogger.SetPath(errorLogPath); err != nil {
|
||||
return err
|
||||
glog.Error(err)
|
||||
}
|
||||
s.logPath.Set(path)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 设置是否开启access log日志功能
|
||||
|
||||
@ -48,7 +48,7 @@ func GetCookie(r *Request) *Cookie {
|
||||
response : r.Response,
|
||||
}
|
||||
c.init()
|
||||
c.server.cookies.Set(r.Id, c)
|
||||
r.Server.cookies.Set(r.Id, c)
|
||||
return c
|
||||
}
|
||||
|
||||
|
||||
@ -52,55 +52,51 @@ func (s *Server)handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
s.closeQueue.PushBack(request)
|
||||
}()
|
||||
|
||||
// 事件 - BeforeServe
|
||||
s.callHookHandler(HOOK_BEFORE_SERVE, request)
|
||||
|
||||
// 路由注册检索
|
||||
handler := (*handlerItem)(nil)
|
||||
parsedItem := s.getServeHandlerWithCache(request)
|
||||
if parsedItem == nil {
|
||||
// 如果路由不匹配,那么执行静态文件检索
|
||||
path := s.paths.Search(r.URL.Path)
|
||||
if path != "" {
|
||||
s.serveFile(request, path)
|
||||
} else {
|
||||
request.Response.WriteStatus(http.StatusNotFound)
|
||||
request.Response.OutputBuffer()
|
||||
}
|
||||
return
|
||||
} else {
|
||||
handler = parsedItem.handler
|
||||
if request.Router == nil {
|
||||
for k, v := range parsedItem.values {
|
||||
request.routerVars[k] = v
|
||||
handler := (*handlerItem)(nil)
|
||||
if !request.exit.Val() {
|
||||
parsedItem := s.getServeHandlerWithCache(request)
|
||||
if parsedItem == nil {
|
||||
// 如果路由不匹配,那么执行静态文件检索
|
||||
path := s.paths.Search(r.URL.Path)
|
||||
if path != "" {
|
||||
s.serveFile(request, path)
|
||||
} else {
|
||||
request.Response.WriteStatus(http.StatusNotFound)
|
||||
}
|
||||
} else {
|
||||
handler = parsedItem.handler
|
||||
if request.Router == nil {
|
||||
for k, v := range parsedItem.values {
|
||||
request.routerVars[k] = v
|
||||
}
|
||||
request.Router = parsedItem.handler.router
|
||||
}
|
||||
request.Router = parsedItem.handler.router
|
||||
}
|
||||
}
|
||||
|
||||
// **********************************************
|
||||
// 以下操作仅对路由控制有效,包括事件处理,不对静态文件有效
|
||||
// **********************************************
|
||||
|
||||
// 事件 - BeforeServe
|
||||
s.callHookHandler("BeforeServe", request)
|
||||
|
||||
// 执行回调控制器/执行对象/方法
|
||||
if handler != nil {
|
||||
s.callServeHandler(handler, request)
|
||||
}
|
||||
|
||||
// 事件 - AfterServe
|
||||
s.callHookHandler("AfterServe", request)
|
||||
s.callHookHandler(HOOK_AFTER_SERVE, request)
|
||||
|
||||
// 设置请求完成时间
|
||||
request.LeaveTime = gtime.Microsecond()
|
||||
|
||||
// 事件 - BeforeOutput
|
||||
s.callHookHandler("BeforeOutput", request)
|
||||
s.callHookHandler(HOOK_BEFORE_OUTPUT, request)
|
||||
// 输出Cookie
|
||||
request.Cookie.Output()
|
||||
// 输出缓冲区
|
||||
request.Response.OutputBuffer()
|
||||
// 事件 - AfterOutput
|
||||
s.callHookHandler("AfterOutput", request)
|
||||
s.callHookHandler(HOOK_AFTER_OUTPUT, request)
|
||||
}
|
||||
|
||||
// 初始化控制器
|
||||
@ -182,12 +178,12 @@ func (s *Server) startCloseQueueLoop() {
|
||||
for {
|
||||
if v := s.closeQueue.PopFront(); v != nil {
|
||||
r := v.(*Request)
|
||||
s.callHookHandler("BeforeClose", r)
|
||||
s.callHookHandler(HOOK_BEFORE_CLOSE, r)
|
||||
// 关闭当前会话的Cookie
|
||||
r.Cookie.Close()
|
||||
// 更新Session会话超时时间
|
||||
r.Session.UpdateExpire()
|
||||
s.callHookHandler("AfterClose", r)
|
||||
s.callHookHandler(HOOK_AFTER_CLOSE, r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
"container/list"
|
||||
"gitee.com/johng/gf/g/util/gregex"
|
||||
"gitee.com/johng/gf/g/util/gstr"
|
||||
)
|
||||
|
||||
|
||||
@ -98,7 +99,7 @@ func (s *Server) setHandler(pattern string, handler *handlerItem, hook ... strin
|
||||
continue
|
||||
}
|
||||
// 判断是否模糊匹配规则
|
||||
if gregex.IsMatchString(`^[:\*]|{[\w\.\-]+}`, v) {
|
||||
if gregex.IsMatchString(`^[:\*]|\{[\w\.\-]+\}|\*`, v) {
|
||||
v = "*fuzz"
|
||||
// 由于是模糊规则,因此这里会有一个*list,用以将后续的路由规则加进来,
|
||||
// 检索会从叶子节点的链表往根节点按照优先级进行检索
|
||||
@ -201,7 +202,13 @@ func (s *Server) patternToRegRule(rule string) (regrule string, names []string)
|
||||
regrule += `/{0,1}(.*)`
|
||||
names = append(names, v[1:])
|
||||
default:
|
||||
s, _ := gregex.ReplaceStringFunc(`{[\w\.\-]+}`, v, func(s string) string {
|
||||
// 特殊字符替换
|
||||
v = gstr.ReplaceByMap(v, map[string]string{
|
||||
`.` : `\.`,
|
||||
`+` : `\+`,
|
||||
`*` : `.*`,
|
||||
})
|
||||
s, _ := gregex.ReplaceStringFunc(`\{[\w\.\-]+\}`, v, func(s string) string {
|
||||
names = append(names, s[1 : len(s) - 1])
|
||||
return `([\w\.\-]+)`
|
||||
})
|
||||
|
||||
@ -42,6 +42,7 @@ func GetSession(r *Request) *Session {
|
||||
data : gmap.NewStringInterfaceMap(),
|
||||
server : s,
|
||||
}
|
||||
s.sessions.Set(sid, ses, s.GetSessionMaxAge())
|
||||
return ses
|
||||
}
|
||||
|
||||
|
||||
@ -472,9 +472,10 @@ func CheckStruct(st interface{}, rules map[string]string, msgs...map[string]inte
|
||||
return CheckMap(params, rules, errMsgs)
|
||||
}
|
||||
|
||||
// 检测单条数据的规则,其中params参数为非必须参数,可以传递所有的校验参数进来,进行多参数对比(部分校验规则需要)
|
||||
// msgs为自定义错误信息,由于同一条数据的校验规则可能存在多条,为方便调用,参数类型支持string/map[string]string,允许传递多个自定义的错误信息,如果类型为string,那么中间使用"|"符号分隔多个自定义错误
|
||||
// values参数为表单联合校验参数,对于需要联合校验的规则有效,如:required-*、same、different
|
||||
// 检测单条数据的规则.
|
||||
// val为校验数据,可以为任意格式;
|
||||
// msgs为自定义错误信息,由于同一条数据的校验规则可能存在多条,为方便调用,参数类型支持string/map[string]string,允许传递多个自定义的错误信息,如果类型为string,那么中间使用"|"符号分隔多个自定义错误;
|
||||
// params参数为表单联合校验参数,对于需要联合校验的规则有效,如:required-*、same、different;
|
||||
func Check(val interface{}, rules string, msgs interface{}, params...map[string]interface{}) map[string]string {
|
||||
// 内部会将参数全部转换为字符串类型进行校验
|
||||
value := strings.TrimSpace(gconv.String(val))
|
||||
|
||||
1
geg/net/ghttp/server/denyroutes/config.toml
Normal file
1
geg/net/ghttp/server/denyroutes/config.toml
Normal file
@ -0,0 +1 @@
|
||||
You're not supposed to view this
|
||||
12
geg/net/ghttp/server/denyroutes/denyroutes.go
Normal file
12
geg/net/ghttp/server/denyroutes/denyroutes.go
Normal file
@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import "gitee.com/johng/gf/g"
|
||||
|
||||
func main() {
|
||||
s := g.Server()
|
||||
s.SetDenyRoutes([]string{
|
||||
"/config*",
|
||||
})
|
||||
s.SetPort(8299)
|
||||
s.Run()
|
||||
}
|
||||
Reference in New Issue
Block a user