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