354 lines
10 KiB
Go
354 lines
10 KiB
Go
|
|
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),
|
|||
|
|
}
|
|||
|
|
}
|