初始化项目
This commit is contained in:
71
trunk/framework/webServer/IWebServer.go
Normal file
71
trunk/framework/webServer/IWebServer.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package webServer
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"goutil/typeUtil"
|
||||
)
|
||||
|
||||
// webserver接口
|
||||
type IWebServer interface {
|
||||
// 注册API
|
||||
// path:注册的访问路径
|
||||
// callback:回调方法
|
||||
// configObj:Handler配置对象
|
||||
RegisterHandler(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig)
|
||||
|
||||
// 注册回调-增加用户自定义数据
|
||||
RegisterHandlerWithUserData(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig, userData interface{})
|
||||
|
||||
RegisterRegexHandler(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig)
|
||||
|
||||
// 注册正则回调-增加用户自定义数据
|
||||
RegisterRegexHandlerWithUserData(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig, userData interface{})
|
||||
|
||||
// 设定Http Header信息
|
||||
SetHeader(header map[string]string)
|
||||
|
||||
// 设定HTTP请求方法
|
||||
SetMethod(method string)
|
||||
|
||||
// 设定当HTTP请求方法无效时,调用的处理器
|
||||
SetInvalidMethodHandler(handler func(*Context))
|
||||
|
||||
// 设置WebServer请求是否经过了负载均衡中转
|
||||
SetIfDelegate(ifDelegate bool)
|
||||
|
||||
// 设定默认页的处理器
|
||||
SetDefaultPageHandler(handler func(*Context))
|
||||
|
||||
// 设定未找到指定的回调时的处理器
|
||||
SetNotFoundPageHandler(handler func(*Context))
|
||||
|
||||
// 设置异常处理函数(默认只会记录在文件)
|
||||
SetUnHandledPanicHandler(handler func(context *Context, errObj interface{}))
|
||||
|
||||
// 设定在Debug模式下是否需要验证IP地址
|
||||
SetIfCheckIPWhenDebug(value bool)
|
||||
|
||||
// 设定当IP无效时调用的处理器
|
||||
SetIPInvalidHandler(handler func(*Context))
|
||||
|
||||
// 设定用于检测参数是否有效的处理器
|
||||
SetParamCheckHandler(handler func(typeUtil.MapData, []string, []string) ([]string, []string, bool))
|
||||
|
||||
// 设定当检测到参数无效时调用的处理器
|
||||
SetParamInvalidHandler(handler func(*Context, []string, []string))
|
||||
|
||||
// 设定处理请求数据的处理器(例如压缩、解密等)
|
||||
SetRequestDataHandler(handler func(*Context, []byte) ([]byte, error))
|
||||
|
||||
// 设定处理响应数据的处理器(例如压缩、加密等)
|
||||
SetResponseDataHandler(handler func(*Context, []byte) ([]byte, error))
|
||||
|
||||
// 设定请求执行时间的处理器
|
||||
SetExecuteTimeHandler(handler func(*Context))
|
||||
|
||||
// http应答处理
|
||||
// responseWriter:应答对象
|
||||
// request:请求对象
|
||||
ServeHTTP(responseWriter http.ResponseWriter, request *http.Request)
|
||||
}
|
||||
374
trunk/framework/webServer/context.go
Normal file
374
trunk/framework/webServer/context.go
Normal file
@@ -0,0 +1,374 @@
|
||||
package webServer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"goutil/logUtil"
|
||||
"goutil/netUtil"
|
||||
"goutil/typeUtil"
|
||||
"goutil/zlibUtil"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMaxMemory = 32 << 20 // 32 MB
|
||||
)
|
||||
|
||||
// 请求上下文对象
|
||||
type Context struct {
|
||||
// 用户自定义数据(注册回调时设置,通过Context传到用户回调) Add:raojianhua Time:2022-02-16 17:00
|
||||
userData interface{}
|
||||
|
||||
// 请求对象
|
||||
request *http.Request
|
||||
|
||||
// 响应对象
|
||||
responseWriter http.ResponseWriter
|
||||
|
||||
// 数据是否已经解析数据
|
||||
ifBodyParsed bool
|
||||
|
||||
// 请求数据
|
||||
bodyContent []byte
|
||||
|
||||
// Form的数据是否已经解析
|
||||
ifFormParsed bool
|
||||
|
||||
// MultipleForm的数据是否已经解析
|
||||
ifMultipartFormParsed bool
|
||||
|
||||
// 是否经过了负载均衡的中转,如果是,则需要通过header获取客户端实际的请求地址
|
||||
ifDelegate bool
|
||||
|
||||
// 请求的开始时间
|
||||
StartTime time.Time
|
||||
|
||||
// 请求的结束时间
|
||||
EndTime time.Time
|
||||
|
||||
// 处理请求数据的处理器(例如压缩、解密等)
|
||||
requestDataHandler func(*Context, []byte) ([]byte, error)
|
||||
|
||||
// 处理响应数据的处理器(例如压缩、加密等)
|
||||
responseDataHandler func(*Context, []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
// 获取用户自定义数据(注册回调时设置,通过Context传到用户回调) Add:raojianhua Time:2022-02-16 17:00
|
||||
func (this *Context) GetUserData() interface{} {
|
||||
return this.userData
|
||||
}
|
||||
|
||||
// 获取请求对象
|
||||
func (this *Context) GetRequest() *http.Request {
|
||||
return this.request
|
||||
}
|
||||
|
||||
// 获取响应对象
|
||||
func (this *Context) GetResponseWriter() http.ResponseWriter {
|
||||
return this.responseWriter
|
||||
}
|
||||
|
||||
// 获取请求路径(不带参数)
|
||||
func (this *Context) GetRequestPath() string {
|
||||
return this.request.URL.Path
|
||||
}
|
||||
|
||||
// 获取请求的客户端的IP地址
|
||||
func (this *Context) GetRequestIP() string {
|
||||
if this.ifDelegate {
|
||||
return netUtil.GetHttpAddr2(this.request).Host
|
||||
}
|
||||
|
||||
return netUtil.GetHttpAddr(this.request).Host
|
||||
}
|
||||
|
||||
// 获取请求执行的秒数
|
||||
func (this *Context) GetExecuteSeconds() int64 {
|
||||
return this.EndTime.Unix() - this.StartTime.Unix()
|
||||
}
|
||||
|
||||
// 格式化context对象
|
||||
func (this *Context) String() string {
|
||||
var bodyContent string
|
||||
if bytes, exist, err := this.GetRequestBytes(); err == nil && exist {
|
||||
bodyContent = string(bytes)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("IP:%s, URL:%s, FormValue:%#v, BodyContent:%s",
|
||||
this.GetRequestIP(), this.GetRequestPath(), this.GetFormValueData(), bodyContent)
|
||||
}
|
||||
|
||||
func (this *Context) parseForm() {
|
||||
if !this.ifFormParsed {
|
||||
// 先保存一份body
|
||||
this.parseBodyContent()
|
||||
|
||||
this.request.ParseMultipartForm(32 << 20)
|
||||
this.ifFormParsed = true
|
||||
}
|
||||
}
|
||||
|
||||
// 获取请求的参数值(包括GET/POST/PUT/DELETE等所有参数)
|
||||
func (this *Context) FormValue(key string) (value string) {
|
||||
this.parseForm()
|
||||
|
||||
return this.request.FormValue(key)
|
||||
}
|
||||
|
||||
// 获取POST的参数值
|
||||
func (this *Context) PostFormValue(key string) (value string) {
|
||||
this.parseForm()
|
||||
|
||||
return this.request.PostFormValue(key)
|
||||
}
|
||||
|
||||
// 获取所有参数的MapData类型(包括GET/POST/PUT/DELETE等所有参数)
|
||||
func (this *Context) GetFormValueData() typeUtil.MapData {
|
||||
this.parseForm()
|
||||
|
||||
valueMap := make(map[string]interface{})
|
||||
for k, v := range this.request.Form {
|
||||
valueMap[k] = v[0]
|
||||
}
|
||||
|
||||
return typeUtil.MapData(valueMap)
|
||||
}
|
||||
|
||||
// 获取POST参数的MapData类型
|
||||
func (this *Context) GetPostFormValueData() typeUtil.MapData {
|
||||
this.parseForm()
|
||||
|
||||
valueMap := make(map[string]interface{})
|
||||
for k, v := range this.request.PostForm {
|
||||
valueMap[k] = v[0]
|
||||
}
|
||||
|
||||
return typeUtil.MapData(valueMap)
|
||||
}
|
||||
|
||||
func (this *Context) parseMultipartForm() {
|
||||
if !this.ifMultipartFormParsed {
|
||||
this.request.ParseMultipartForm(defaultMaxMemory)
|
||||
this.ifMultipartFormParsed = true
|
||||
}
|
||||
}
|
||||
|
||||
// 获取MultipartForm的MapData类型
|
||||
func (this *Context) GetMultipartFormValueData() typeUtil.MapData {
|
||||
this.parseMultipartForm()
|
||||
|
||||
valueMap := make(map[string]interface{})
|
||||
if this.request.MultipartForm != nil {
|
||||
for k, v := range this.request.MultipartForm.Value {
|
||||
valueMap[k] = v[0]
|
||||
}
|
||||
}
|
||||
|
||||
return typeUtil.MapData(valueMap)
|
||||
}
|
||||
|
||||
func (this *Context) parseBodyContent() (err error) {
|
||||
if this.ifBodyParsed {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
this.request.Body.Close()
|
||||
this.ifBodyParsed = true
|
||||
|
||||
if len(this.bodyContent) > 0 {
|
||||
this.request.Body = ioutil.NopCloser(bytes.NewBuffer(this.bodyContent))
|
||||
}
|
||||
}()
|
||||
|
||||
this.bodyContent, err = ioutil.ReadAll(this.request.Body)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("url:%s,read body failed. Err:%s", this.GetRequestPath(), err))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求字节数据
|
||||
// 返回值:
|
||||
// []byte:请求字节数组
|
||||
// exist:是否存在数据
|
||||
// error:错误信息
|
||||
func (this *Context) GetRequestBytes() (result []byte, exist bool, err error) {
|
||||
if err = this.parseBodyContent(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result = this.bodyContent
|
||||
if result == nil || len(result) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// handle request data
|
||||
if this.requestDataHandler != nil {
|
||||
if result, err = this.requestDataHandler(this, result); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求字符串数据
|
||||
// 返回值:
|
||||
// result:请求字符串数据
|
||||
// exist:是否存在数据
|
||||
// error:错误信息
|
||||
func (this *Context) GetRequestString() (result string, exist bool, err error) {
|
||||
var data []byte
|
||||
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
|
||||
return
|
||||
}
|
||||
|
||||
result = string(data)
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 反序列化为对象(JSON)
|
||||
// obj:反序列化结果数据
|
||||
// isCompressed:数据是否已经被压缩
|
||||
// 返回值:
|
||||
// 错误对象
|
||||
func (this *Context) Unmarshal(obj interface{}) (exist bool, err error) {
|
||||
var data []byte
|
||||
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal
|
||||
if err = json.Unmarshal(data, &obj); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Unmarshal %s failed. Err::%s", string(data), err))
|
||||
return
|
||||
}
|
||||
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 反序列化为对象(zlib+JSON)
|
||||
// obj:反序列化结果数据
|
||||
// isCompressed:数据是否已经被压缩
|
||||
// 返回值:
|
||||
// 错误对象
|
||||
func (this *Context) UnmarshalZlib(obj interface{}) (exist bool, err error) {
|
||||
var data []byte
|
||||
if data, exist, err = this.GetRequestBytes(); err != nil || !exist {
|
||||
return
|
||||
}
|
||||
|
||||
zlibBytes, err := zlibUtil.Decompress(data)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Decompress %v failed. Err::%s", string(data), err))
|
||||
return
|
||||
}
|
||||
|
||||
// Unmarshal
|
||||
if err = json.Unmarshal(zlibBytes, &obj); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Unmarshal %s failed. Err::%s", string(data), err))
|
||||
return
|
||||
}
|
||||
|
||||
exist = true
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (this *Context) writeBytes(data []byte) error {
|
||||
var err error
|
||||
if this.responseDataHandler != nil {
|
||||
if data, err = this.responseDataHandler(this, data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = this.responseWriter.Write(data)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 输出字符串给客户端
|
||||
func (this *Context) WriteString(result string) error {
|
||||
return this.writeBytes([]byte(result))
|
||||
}
|
||||
|
||||
// 输出json数据给客户端
|
||||
func (this *Context) WriteJson(result interface{}) error {
|
||||
data, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Marshal %v failed. Err::%s", result, err))
|
||||
return err
|
||||
}
|
||||
|
||||
return this.writeBytes(data)
|
||||
}
|
||||
|
||||
// 输出zlib+json数据给客户端
|
||||
func (this *Context) WriteZlibJson(result interface{}) error {
|
||||
data, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Marshal %v failed. Err::%s", result, err))
|
||||
return err
|
||||
}
|
||||
|
||||
zlibBytes, err := zlibUtil.Compress(data, zlib.DefaultCompression)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("Compress %v failed. Err::%s", string(data), err))
|
||||
return err
|
||||
}
|
||||
|
||||
return this.writeBytes(zlibBytes)
|
||||
}
|
||||
|
||||
/*
|
||||
Http状态码301和302概念简单区别
|
||||
302重定向表示临时性转移(Temporarily Moved ),当一个网页URL需要短期变化时使用。 301重定向是永久的重定向,搜索引擎在抓取新内容的同时也将旧的网址替换为重定向之后的网址。 302重定向是临时的重定向,搜索引擎会抓取新的内容而保留旧的网址。
|
||||
如果是短链,需要每次都访问原来的短链地址,以便于进行统计,则使用302重定向
|
||||
*/
|
||||
// 重定向到其它页面(301)
|
||||
func (this *Context) RedirectTo(url string) {
|
||||
this.responseWriter.Header().Set("Location", url)
|
||||
this.responseWriter.WriteHeader(301)
|
||||
}
|
||||
|
||||
// 重定向到其它页面(302)
|
||||
func (this *Context) RedirectTo302(url string) {
|
||||
this.responseWriter.Header().Set("Location", url)
|
||||
this.responseWriter.WriteHeader(302)
|
||||
}
|
||||
|
||||
// 新建API上下文对象
|
||||
// request:请求对象
|
||||
// responseWriter:应答写对象
|
||||
// _ifDelegate:是否经过负载均衡
|
||||
// 返回值:
|
||||
// *Context:上下文
|
||||
func newContext(request *http.Request, responseWriter http.ResponseWriter,
|
||||
requestDataHandler func(*Context, []byte) ([]byte, error),
|
||||
responseDataHandler func(*Context, []byte) ([]byte, error),
|
||||
_ifDelegate bool) *Context {
|
||||
return &Context{
|
||||
request: request,
|
||||
responseWriter: responseWriter,
|
||||
StartTime: time.Now(),
|
||||
EndTime: time.Now(),
|
||||
requestDataHandler: requestDataHandler,
|
||||
responseDataHandler: responseDataHandler,
|
||||
ifDelegate: _ifDelegate,
|
||||
}
|
||||
}
|
||||
82
trunk/framework/webServer/doc.go
Normal file
82
trunk/framework/webServer/doc.go
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
此包提供通用的HTTP/HTTPS服务器功能;
|
||||
使用方法如下:
|
||||
1、初始化一个HttpServer/HttpsServer
|
||||
server := NewHttpServer(addr string, isCheckIP bool)
|
||||
或
|
||||
server := NewHttpsServer(addr, certFileName, keyFileName string, isCheckIP bool)
|
||||
其中参数说明如下:
|
||||
addr:服务器监听地址
|
||||
isCheckIP:是否需要验证客户端IP(此设置针对所有的请求,对于每个请求也可以单独设置;以此设置为优先)
|
||||
certFileName:证书文件的路径
|
||||
keyFileName:密钥文件的路径
|
||||
|
||||
2、设置server的属性
|
||||
在服务器运行过程中,会有一些默认的行为,如果想要改变默认行为,可以通过调用以下的方法进行设置
|
||||
|
||||
1)、设定Http Header信息
|
||||
SetHeader(header map[string]string)
|
||||
默认的Http Header为空;如果设定了Http Header,则在每次请求时,都会给ResponseWriter加上该header属性
|
||||
2)、设定HTTP请求方法
|
||||
SetMethod(method string)
|
||||
默认情况下,对请求的方法没有任何限制;如果设定了Method,则只允许该Method访问
|
||||
3)、设定当HTTP请求方法无效时,调用的处理器
|
||||
SetInvalidMethodHandler(handler func(*Context))
|
||||
默认情况下,如果请求方法与所设置的方法不一致时,会返回406错误;如果设置了此属性,则会调用此属性进行处理
|
||||
4)、设定默认页的处理器
|
||||
SetDefaultPageHandler(handler func(*Context))
|
||||
默认页指的是/, /favicon.ico这两个页面;默认情况下,仅仅是输出Welcome to home page.;如果需要针对做一些处理,可以设置此属性
|
||||
5)、设定未找到指定的回调时的处理器
|
||||
SetNotFoundPageHandler(handler func(*Context))
|
||||
当服务器找不到对应的地址的Handler时,会返回404错误。如果需要处理一些非固定的地址时,可以使用此方法;比如回调地址中包含AppId,所以导致地址可变
|
||||
6)、设定在Debug模式下是否需要验证IP地址
|
||||
SetIfCheckIPWhenDebug(value bool)
|
||||
默认情况下,在DEBUG模式时不验证IP;可以通过此属性改变此此行为
|
||||
7)、设定当IP无效时调用的处理器
|
||||
SetIPInvalidHandler(handler func(*Context))
|
||||
当需要验证IP并且IP无效时,默认情况下会返回401错误;如果设定了此属性,则可以改变该行为
|
||||
8)、设定当检测到参数无效时调用的处理器
|
||||
SetParamInvalidHandler(handler func(*Context))
|
||||
当检测到参数无效时,默认情况下会返回500错误;如果设置了此属性,则可以改变该行为
|
||||
9)、设定处理请求数据的处理器(例如压缩、解密等)
|
||||
SetRequestDataHandler(handler func(*Context, []byte) ([]byte, error))
|
||||
如果设定此属性,则在处理接收到的请求数据时,会调用此属性
|
||||
10)、设定处理响应数据的处理器(例如压缩、加密等)
|
||||
SetResponseDataHandler(handler func(*Context, []byte) ([]byte, error))
|
||||
如果设定此属性,则在处理返回给客户端的数据时,会调用此属性
|
||||
11)、设定请求执行时间的处理器
|
||||
SetExecuteTimeHandler(handler func(*Context))
|
||||
如果在请求结束后想要处理调用的时间,则需要设置此属性;例如请求时间过长则记录日志等
|
||||
|
||||
3、注册handler
|
||||
server.RegisterHandler(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig)
|
||||
参数如下:
|
||||
// path:注册的访问路径
|
||||
// callback:回调方法
|
||||
// configObj:Handler配置对象
|
||||
例如:server.RegisterHandler("/get/notice", getNoticeConfig, &webServer.HandlerConfig{IsCheckIP: false, ParamNameList: []string{"appid"}})
|
||||
|
||||
4、启动对应的服务器
|
||||
server.Start(wg *sync.WaitGroup)
|
||||
|
||||
5、context中提供了很多实用的方法
|
||||
1)、GetRequestPath() string:获取请求路径(该路径不带参数)
|
||||
2)、GetRequestIP() string:获取请求的客户端的IP地址
|
||||
3)、GetExecuteSeconds() int64:获取请求执行的秒数。当然也可以通过获取StartTime, EndTime属性自己进行更高精度的处理
|
||||
4)、String() string:将context里面的内容进行格式化,主要用于记录日志
|
||||
5)、FormValue(key string) string:获取请求的参数值(包括GET/POST/PUT/DELETE等所有参数)
|
||||
6)、PostFormValue(key string) string:获取POST的参数值
|
||||
7)、GetFormValueData() typeUtil.MapData:获取所有参数的MapData类型(包括GET/POST/PUT/DELETE等所有参数)
|
||||
8)、GetPostFormValueData() typeUtil.MapData:获取POST参数的MapData类型
|
||||
9)、GetMultipartFormValueData() typeUtil.MapData:获取MultipartForm的MapData类型
|
||||
10)、GetRequestBytes() (result []byte, exists bool, err error):获取请求字节数据
|
||||
11)、GetRequestString() (result string, exists bool, err error):获取请求字符串数据
|
||||
12)、Unmarshal(obj interface{}) (exists bool, err error):反序列化为对象(JSON)
|
||||
13)、WriteString(result string):输出字符串给客户端
|
||||
14)、WriteJson(result interface{}):输出json数据给客户端
|
||||
15)、RedirectTo(url string):重定向到其它页面
|
||||
如果以上的方法不能满足需求,则可以调用以下的方法来获取原始的Request/ResponseWriter对象进行处理
|
||||
16)、GetRequest() *http.Request:获取请求对象
|
||||
17)、GetResponseWriter() http.ResponseWriter:获取响应对象
|
||||
*/
|
||||
package webServer
|
||||
162
trunk/framework/webServer/handler.go
Normal file
162
trunk/framework/webServer/handler.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package webServer
|
||||
|
||||
import (
|
||||
"Framework/ipMgr"
|
||||
"goutil/debugUtil"
|
||||
"goutil/typeUtil"
|
||||
)
|
||||
|
||||
// 参数传输类型
|
||||
type ParamTransferType string
|
||||
|
||||
const (
|
||||
// 以Form表单形式来传递参数
|
||||
Con_Form ParamTransferType = "Form"
|
||||
// 以二进制流形式来传递参数
|
||||
Con_Stream ParamTransferType = "Stream"
|
||||
)
|
||||
|
||||
type handlerFunc func(*Context)
|
||||
|
||||
// 请求处理配置对象
|
||||
type HandlerConfig struct {
|
||||
// 是否需要验证IP
|
||||
IsCheckIP bool
|
||||
|
||||
// 参数类型
|
||||
ParamTransferType ParamTransferType
|
||||
|
||||
// 方法参数名称集合
|
||||
ParamNameList []string
|
||||
|
||||
// 非空参数名称集合
|
||||
NotEmptyParamNameList []string
|
||||
}
|
||||
|
||||
// 请求处理对象
|
||||
type handler struct {
|
||||
// 用户自定义数据(注册回调时设置,通过Context传到用户回调) Add:raojianhua Time:2022-02-16 17:00
|
||||
userData interface{}
|
||||
|
||||
// 注册的访问路径
|
||||
path string
|
||||
|
||||
// 方法定义
|
||||
funcObj handlerFunc
|
||||
|
||||
// 请求处理配置对象
|
||||
configObj *HandlerConfig
|
||||
|
||||
// 正则表达式
|
||||
regex bool
|
||||
}
|
||||
|
||||
// 检查IP是否合法
|
||||
func (this *handler) checkIP(context *Context, ifCheckIPWhenDebug bool) bool {
|
||||
if this.configObj == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if this.configObj.IsCheckIP == false {
|
||||
return true
|
||||
}
|
||||
|
||||
if debugUtil.IsDebug() == true && ifCheckIPWhenDebug == false {
|
||||
return true
|
||||
}
|
||||
|
||||
if ipMgr.IsIpValid(context.GetRequestIP()) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 检测参数
|
||||
func (this *handler) checkParam(context *Context, methodName string, paramCheckHandler func(paramMap typeUtil.MapData, paramNameList []string, notEmptyParamList []string) ([]string, []string, bool)) (missParamList []string, emptyParamList []string, valid bool) {
|
||||
valid = true
|
||||
|
||||
if this.configObj == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 获取方法的参数集合
|
||||
var dataMap typeUtil.MapData
|
||||
switch this.configObj.ParamTransferType {
|
||||
case Con_Stream:
|
||||
data := new(map[string]interface{})
|
||||
if exist, err := context.Unmarshal(data); err != nil || !exist {
|
||||
valid = false
|
||||
return
|
||||
}
|
||||
dataMap = typeUtil.NewMapData(*data)
|
||||
default:
|
||||
if methodName == "POST" {
|
||||
dataMap = context.GetPostFormValueData()
|
||||
} else {
|
||||
dataMap = context.GetFormValueData()
|
||||
}
|
||||
}
|
||||
|
||||
// 定义默认的参数验证方法
|
||||
defaultParamCheckHandler := func(paramMap typeUtil.MapData, paramNameList []string, notEmptyParamList []string) (_missParamList []string, _emptyParamList []string, _valid bool) {
|
||||
_valid = true
|
||||
|
||||
// 遍历判断每一个参数是否存在;为了搜集所有的参数,所以不会提前返回
|
||||
for _, name := range paramNameList {
|
||||
if _, exist := paramMap[name]; !exist {
|
||||
_missParamList = append(_missParamList, name)
|
||||
_valid = false
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range notEmptyParamList {
|
||||
if value, _ := paramMap[name]; value == "" {
|
||||
_emptyParamList = append(_emptyParamList, name)
|
||||
_valid = false
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 如果没有指定验证参数的方法,就使用默认方法
|
||||
if paramCheckHandler == nil {
|
||||
missParamList, emptyParamList, valid = defaultParamCheckHandler(dataMap, this.configObj.ParamNameList, this.configObj.NotEmptyParamNameList)
|
||||
} else {
|
||||
missParamList, emptyParamList, valid = paramCheckHandler(dataMap, this.configObj.ParamNameList, this.configObj.NotEmptyParamNameList)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 检测POST参数
|
||||
func (this *handler) checkPostParam(context *Context) bool {
|
||||
if this.configObj == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, name := range this.configObj.ParamNameList {
|
||||
if _, exist := context.GetPostFormValueData()[name]; !exist {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range this.configObj.NotEmptyParamNameList {
|
||||
if value, _ := context.GetPostFormValueData()[name]; value == "" {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 创建新的请求方法对象
|
||||
func newHandler(path string, funcObj handlerFunc, configObj *HandlerConfig) *handler {
|
||||
return &handler{
|
||||
path: path,
|
||||
funcObj: funcObj,
|
||||
configObj: configObj,
|
||||
regex: false,
|
||||
}
|
||||
}
|
||||
82
trunk/framework/webServer/httpServer.go
Normal file
82
trunk/framework/webServer/httpServer.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package webServer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"goutil/logUtil"
|
||||
)
|
||||
|
||||
// Http服务器对象
|
||||
type HttpServer struct {
|
||||
addr string
|
||||
IWebServer
|
||||
server http.Server
|
||||
}
|
||||
|
||||
func (this *HttpServer) SetAddr(addr string) {
|
||||
this.addr = addr
|
||||
this.server.Addr = addr
|
||||
}
|
||||
|
||||
// 启动HttpServer
|
||||
func (this *HttpServer) Start(wg *sync.WaitGroup) {
|
||||
defer func() {
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
// 开启监听
|
||||
msg := fmt.Sprintf("http server begins to listen on: %s...", this.addr)
|
||||
fmt.Println(msg)
|
||||
logUtil.InfoLog(msg)
|
||||
|
||||
if err := this.server.ListenAndServe(); err != nil {
|
||||
panic(fmt.Sprintf("http server ListenAndServe Error:%v", err))
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新的HttpServer
|
||||
// isCheckIP:该属性已丢弃,可以任意赋值
|
||||
func NewHttpServer(addr string, isCheckIP bool) *HttpServer {
|
||||
webServerObj := NewWebServer(isCheckIP)
|
||||
|
||||
return &HttpServer{
|
||||
addr: addr,
|
||||
IWebServer: webServerObj,
|
||||
server: http.Server{
|
||||
Addr: addr,
|
||||
Handler: webServerObj,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新的HttpServer
|
||||
func NewHttpServer2(addr string, webServerObj IWebServer) *HttpServer {
|
||||
return &HttpServer{
|
||||
addr: addr,
|
||||
IWebServer: webServerObj,
|
||||
server: http.Server{
|
||||
Addr: addr,
|
||||
Handler: webServerObj,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新的HttpServer
|
||||
// isCheckIP:该属性已丢弃,可以任意赋值
|
||||
func NewHttpServer3(addr string, isCheckIP bool, readTimeout time.Duration, readHeaderTimeout time.Duration, writeTimeout time.Duration) *HttpServer {
|
||||
webServerObj := NewWebServer(isCheckIP)
|
||||
return &HttpServer{
|
||||
addr: addr,
|
||||
IWebServer: webServerObj,
|
||||
server: http.Server{
|
||||
Addr: addr,
|
||||
Handler: webServerObj,
|
||||
ReadTimeout: readTimeout,
|
||||
ReadHeaderTimeout: readHeaderTimeout,
|
||||
WriteTimeout: writeTimeout,
|
||||
},
|
||||
}
|
||||
}
|
||||
70
trunk/framework/webServer/httpsServer.go
Normal file
70
trunk/framework/webServer/httpsServer.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package webServer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"goutil/logUtil"
|
||||
)
|
||||
|
||||
// Https服务器对象
|
||||
type HttpsServer struct {
|
||||
addr string
|
||||
certFileName string
|
||||
keyFileName string
|
||||
IWebServer
|
||||
server http.Server
|
||||
}
|
||||
|
||||
func (this *HttpsServer) SetAddr(addr string) {
|
||||
this.addr = addr
|
||||
this.server.Addr = addr
|
||||
}
|
||||
|
||||
// 启动HttpsServer
|
||||
func (this *HttpsServer) Start(wg *sync.WaitGroup) {
|
||||
defer func() {
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
// 开启监听
|
||||
msg := fmt.Sprintf("http server begins to listen on: %s...", this.addr)
|
||||
fmt.Println(msg)
|
||||
logUtil.InfoLog(msg)
|
||||
|
||||
if err := this.server.ListenAndServeTLS(this.certFileName, this.keyFileName); err != nil {
|
||||
panic(fmt.Sprintf("https server ListenAndServeTLS Error:%v", err))
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新的HttpsServer
|
||||
// isCheckIP:该属性已丢弃,可以任意赋值
|
||||
func NewHttpsServer(addr, certFileName, keyFileName string, isCheckIP bool) *HttpsServer {
|
||||
webServerObj := NewWebServer(isCheckIP)
|
||||
|
||||
return &HttpsServer{
|
||||
addr: addr,
|
||||
certFileName: certFileName,
|
||||
keyFileName: keyFileName,
|
||||
IWebServer: webServerObj,
|
||||
server: http.Server{
|
||||
Addr: addr,
|
||||
Handler: webServerObj,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新的HttpsServer
|
||||
func NewHttpsServer2(addr, certFileName, keyFileName string, webServerObj IWebServer) *HttpsServer {
|
||||
return &HttpsServer{
|
||||
addr: addr,
|
||||
certFileName: certFileName,
|
||||
keyFileName: keyFileName,
|
||||
IWebServer: webServerObj,
|
||||
server: http.Server{
|
||||
Addr: addr,
|
||||
Handler: webServerObj,
|
||||
},
|
||||
}
|
||||
}
|
||||
353
trunk/framework/webServer/webServer.go
Normal file
353
trunk/framework/webServer/webServer.go
Normal file
@@ -0,0 +1,353 @@
|
||||
package webServer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"goutil/logUtil"
|
||||
"goutil/typeUtil"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultPageMap = make(map[string]bool)
|
||||
)
|
||||
|
||||
func init() {
|
||||
defaultPageMap["/"] = true
|
||||
defaultPageMap["/favicon.ico"] = true
|
||||
}
|
||||
|
||||
// web服务对象
|
||||
type WebServer struct {
|
||||
// 所有对外提供的处理器集合
|
||||
handlerMap map[string]*handler
|
||||
|
||||
// 需要应用的Header集合
|
||||
headerMap map[string]string
|
||||
|
||||
// 指定的HTTP请求方法,如果不指定则任意方法均有效
|
||||
specifiedMethod string
|
||||
|
||||
// 当HTTP请求方法无效时,调用的处理器
|
||||
invalidMethodHandler func(*Context)
|
||||
|
||||
// 默认页的处理器(默认页指的是/或/favicon.ico,通常是被负载均衡器调用或在浏览器中直接访问,而不会被程序调用)
|
||||
defaultPageHandler func(*Context)
|
||||
|
||||
// 未找到指定的回调时的处理器,通常是因为该url是可变的,而不是固定的
|
||||
notFoundPageHandler func(*Context)
|
||||
|
||||
// 未处理的异常处理函数
|
||||
unHandledPanicHandler func(context *Context, errObj interface{})
|
||||
|
||||
// ifDelegate:是否经过负责均衡中转(经过负载均衡中转后,Request的地址需要从Header获取)
|
||||
ifDelegate bool
|
||||
|
||||
// 在Debug模式下是否需要验证IP地址,默认情况下不验证
|
||||
ifCheckIPWhenDebug bool
|
||||
|
||||
// 当IP无效时调用的处理器
|
||||
ipInvalidHandler func(*Context)
|
||||
|
||||
// 用于检测参数是否有效的处理器
|
||||
paramCheckHandler func(typeUtil.MapData, []string, []string) ([]string, []string, bool)
|
||||
|
||||
// 当检测到参数无效时调用的处理器
|
||||
paramInvalidHandler func(*Context, []string, []string)
|
||||
|
||||
// 处理请求数据的处理器(例如压缩、解密等)
|
||||
requestDataHandler func(*Context, []byte) ([]byte, error)
|
||||
|
||||
// 处理响应数据的处理器(例如压缩、加密等)
|
||||
responseDataHandler func(*Context, []byte) ([]byte, error)
|
||||
|
||||
// 请求执行时间的处理器
|
||||
executeTimeHandler func(*Context)
|
||||
}
|
||||
|
||||
// 注册API
|
||||
// path:注册的访问路径
|
||||
// callback:回调方法
|
||||
// configObj:Handler配置对象
|
||||
func (this *WebServer) RegisterHandler(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig) {
|
||||
// 判断是否已经注册过,避免命名重复
|
||||
if _, exist := this.handlerMap[path]; exist {
|
||||
panic(fmt.Sprintf("%s has been registered, please try a new path", path))
|
||||
}
|
||||
|
||||
this.handlerMap[path] = newHandler(path, handlerFuncObj, configObj)
|
||||
}
|
||||
|
||||
// 注册回调-增加用户自定义数据
|
||||
func (this *WebServer) RegisterHandlerWithUserData(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig, userData interface{}) {
|
||||
// 判断是否已经注册过,避免命名重复
|
||||
if _, exist := this.handlerMap[path]; exist {
|
||||
panic(fmt.Sprintf("%s has been registered, please try a new path", path))
|
||||
}
|
||||
|
||||
handler := newHandler(path, handlerFuncObj, configObj)
|
||||
handler.userData = userData
|
||||
this.handlerMap[path] = handler
|
||||
}
|
||||
|
||||
// 注册正则表式路径API
|
||||
// path:注册的访问路径
|
||||
// callback:回调方法
|
||||
// configObj:Handler配置对象
|
||||
func (this *WebServer) RegisterRegexHandler(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig) {
|
||||
// 判断是否已经注册过,避免命名重复
|
||||
if _, exist := this.handlerMap[path]; exist {
|
||||
panic(fmt.Sprintf("%s has been registered, please try a new path", path))
|
||||
}
|
||||
|
||||
handler := newHandler(path, handlerFuncObj, configObj)
|
||||
handler.regex = true
|
||||
this.handlerMap[path] = handler
|
||||
}
|
||||
|
||||
// 注册正则回调-增加用户自定义数据
|
||||
func (this *WebServer) RegisterRegexHandlerWithUserData(path string, handlerFuncObj handlerFunc, configObj *HandlerConfig, userData interface{}) {
|
||||
// 判断是否已经注册过,避免命名重复
|
||||
if _, exist := this.handlerMap[path]; exist {
|
||||
panic(fmt.Sprintf("%s has been registered, please try a new path", path))
|
||||
}
|
||||
|
||||
handler := newHandler(path, handlerFuncObj, configObj)
|
||||
handler.userData = userData
|
||||
handler.regex = true
|
||||
this.handlerMap[path] = handler
|
||||
}
|
||||
|
||||
// 获取请求方法
|
||||
// path:方法名称
|
||||
// 返回值:
|
||||
// 请求方法
|
||||
// 是否存在
|
||||
func (this *WebServer) getHandler(path string) (handlerObj *handler, exist bool) {
|
||||
handlerObj, exist = this.handlerMap[path]
|
||||
|
||||
if !exist {
|
||||
for _, handler := range this.handlerMap {
|
||||
if handler.regex {
|
||||
match, _ := regexp.MatchString(handler.path, path)
|
||||
if match {
|
||||
return handler, true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 设定Http Header信息
|
||||
func (this *WebServer) SetHeader(header map[string]string) {
|
||||
this.headerMap = header
|
||||
}
|
||||
|
||||
// 处理Http Header信息
|
||||
func (this *WebServer) handleHeader(context *Context) {
|
||||
if this.headerMap != nil && len(this.headerMap) > 0 {
|
||||
for k, v := range this.headerMap {
|
||||
context.responseWriter.Header().Set(k, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设定HTTP请求方法
|
||||
func (this *WebServer) SetMethod(method string) {
|
||||
this.specifiedMethod = method
|
||||
}
|
||||
|
||||
// 设定当HTTP请求方法无效时,调用的处理器
|
||||
func (this *WebServer) SetInvalidMethodHandler(handler func(*Context)) {
|
||||
this.invalidMethodHandler = handler
|
||||
}
|
||||
|
||||
// 处理HTTP请求方法
|
||||
// 返回值
|
||||
// isTerminate:是否终止本次请求
|
||||
func (this *WebServer) handleMethod(context *Context) (isTerminate bool) {
|
||||
if this.specifiedMethod != "" {
|
||||
if context.request.Method != this.specifiedMethod {
|
||||
if this.invalidMethodHandler != nil {
|
||||
this.invalidMethodHandler(context)
|
||||
} else {
|
||||
http.Error(context.responseWriter, fmt.Sprintf("Expected %s Method", this.specifiedMethod), 406)
|
||||
}
|
||||
isTerminate = true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 设定默认页的处理器
|
||||
func (this *WebServer) SetDefaultPageHandler(handler func(*Context)) {
|
||||
this.defaultPageHandler = handler
|
||||
}
|
||||
|
||||
// 处理默认页
|
||||
// 返回值
|
||||
// isTerminate:是否终止本次请求
|
||||
func (this *WebServer) handleDefaultPage(context *Context) (isTerminate bool) {
|
||||
// 首页进行特别处理
|
||||
if _, exist := defaultPageMap[context.GetRequestPath()]; exist {
|
||||
if this.defaultPageHandler != nil {
|
||||
this.defaultPageHandler(context)
|
||||
} else {
|
||||
context.WriteString("Welcome to home page.")
|
||||
}
|
||||
isTerminate = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 设定未找到指定的回调时的处理器
|
||||
func (this *WebServer) SetNotFoundPageHandler(handler func(*Context)) {
|
||||
this.notFoundPageHandler = handler
|
||||
}
|
||||
|
||||
// 设置异常处理函数(默认只会记录在文件)
|
||||
func (this *WebServer) SetUnHandledPanicHandler(handler func(context *Context, errObj interface{})) {
|
||||
this.unHandledPanicHandler = handler
|
||||
}
|
||||
|
||||
// 设定在Debug模式下是否需要验证IP地址
|
||||
func (this *WebServer) SetIfCheckIPWhenDebug(value bool) {
|
||||
this.ifCheckIPWhenDebug = value
|
||||
}
|
||||
|
||||
// 设定当IP无效时调用的处理器
|
||||
func (this *WebServer) SetIPInvalidHandler(handler func(*Context)) {
|
||||
this.ipInvalidHandler = handler
|
||||
}
|
||||
|
||||
// 设定用于检测参数是否有效的处理器
|
||||
func (this *WebServer) SetParamCheckHandler(handler func(typeUtil.MapData, []string, []string) ([]string, []string, bool)) {
|
||||
this.paramCheckHandler = handler
|
||||
}
|
||||
|
||||
// 设定当检测到参数无效时调用的处理器
|
||||
func (this *WebServer) SetParamInvalidHandler(handler func(*Context, []string, []string)) {
|
||||
this.paramInvalidHandler = handler
|
||||
}
|
||||
|
||||
// 设定处理请求数据的处理器(例如压缩、解密等)
|
||||
func (this *WebServer) SetRequestDataHandler(handler func(*Context, []byte) ([]byte, error)) {
|
||||
this.requestDataHandler = handler
|
||||
}
|
||||
|
||||
// 设定处理响应数据的处理器(例如压缩、加密等)
|
||||
func (this *WebServer) SetResponseDataHandler(handler func(*Context, []byte) ([]byte, error)) {
|
||||
this.responseDataHandler = handler
|
||||
}
|
||||
|
||||
// 设定请求执行时间的处理器
|
||||
func (this *WebServer) SetExecuteTimeHandler(handler func(*Context)) {
|
||||
this.executeTimeHandler = handler
|
||||
}
|
||||
|
||||
// 处理请求执行时间逻辑
|
||||
func (this *WebServer) handleExecuteTime(context *Context) {
|
||||
if this.executeTimeHandler != nil {
|
||||
this.executeTimeHandler(context)
|
||||
}
|
||||
}
|
||||
|
||||
// 设置WebServer请求是否经过了负载均衡中转
|
||||
func (this *WebServer) SetIfDelegate(ifDelegate bool) {
|
||||
this.ifDelegate = ifDelegate
|
||||
}
|
||||
|
||||
// http应答处理
|
||||
// responseWriter:应答对象
|
||||
// request:请求对象
|
||||
func (this *WebServer) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) {
|
||||
// 构造上下文对象
|
||||
context := newContext(request, responseWriter, this.requestDataHandler, this.responseDataHandler, this.ifDelegate)
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if this.unHandledPanicHandler != nil {
|
||||
this.unHandledPanicHandler(context, r)
|
||||
} else {
|
||||
logUtil.LogUnknownError(r)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// 处理Http Header信息
|
||||
this.handleHeader(context)
|
||||
|
||||
// 处理默认页
|
||||
if this.handleDefaultPage(context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 处理返回值信息
|
||||
defer func() {
|
||||
// 处理请求执行时间逻辑
|
||||
this.handleExecuteTime(context)
|
||||
}()
|
||||
|
||||
// 处理请求方法
|
||||
if this.handleMethod(context) {
|
||||
return
|
||||
}
|
||||
|
||||
// 根据路径选择不同的处理方法
|
||||
var handlerObj *handler
|
||||
var exist bool
|
||||
if handlerObj, exist = this.getHandler(context.GetRequestPath()); !exist {
|
||||
if this.notFoundPageHandler != nil {
|
||||
this.notFoundPageHandler(context)
|
||||
} else {
|
||||
http.Error(context.responseWriter, "访问的页面不存在", 404)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 将用户自定义数据通过Context传入回调
|
||||
context.userData = handlerObj.userData
|
||||
|
||||
// Check IP
|
||||
if handlerObj.checkIP(context, this.ifCheckIPWhenDebug) == false {
|
||||
if this.ipInvalidHandler != nil {
|
||||
this.ipInvalidHandler(context)
|
||||
} else {
|
||||
http.Error(context.responseWriter, "你的IP不允许访问,请联系管理员", 401)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Check Param
|
||||
if missParamList, emptyParamList, valid := handlerObj.checkParam(context, this.specifiedMethod, this.paramCheckHandler); valid == false {
|
||||
if this.paramInvalidHandler != nil {
|
||||
this.paramInvalidHandler(context, missParamList, emptyParamList)
|
||||
} else {
|
||||
if missParamList != nil && len(missParamList) > 0 {
|
||||
http.Error(context.responseWriter, fmt.Sprintf("你的参数不正确,请检查,缺少以下参数:%s", strings.Join(missParamList, ",")), 500)
|
||||
} else {
|
||||
http.Error(context.responseWriter, fmt.Sprintf("你的参数不正确,请检查,以下参数为空:%s", strings.Join(emptyParamList, ",")), 500)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Call Function
|
||||
handlerObj.funcObj(context)
|
||||
|
||||
context.EndTime = time.Now()
|
||||
}
|
||||
|
||||
// 新建WebServer对象
|
||||
// isCheckIP:该属性已丢弃,可以任意赋值
|
||||
func NewWebServer(isCheckIP bool) *WebServer {
|
||||
return &WebServer{
|
||||
handlerMap: make(map[string]*handler),
|
||||
headerMap: make(map[string]string),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user