初始化项目

This commit is contained in:
皮蛋13361098506
2025-01-06 16:01:02 +08:00
commit 1b77f62820
575 changed files with 69193 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
package webServer
import (
"net/http"
"goutil/typeUtil"
)
// webserver接口
type IWebServer interface {
// 注册API
// path注册的访问路径
// callback回调方法
// configObjHandler配置对象
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)
}

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

View 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回调方法
// configObjHandler配置对象
例如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

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

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

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

View 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回调方法
// configObjHandler配置对象
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回调方法
// configObjHandler配置对象
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),
}
}