package easyophdl import ( "fmt" "git.swzry.com/zry/go-zSshRpcServer/server" "github.com/bitly/go-simplejson" "sync" ) type EasyOperationHandleFunc func(request *EasyOpHdlRequest, response *EasyOpHdlResponse) type EasyOperationHandler struct { IsDebug bool SuggestWhenNotFound bool LogSuccessAccess bool LogFailedAccess bool logger zsshrpc_server.SvrLogFunc handlerMap map[string]map[zsshrpc_server.ZSshRpcMethod]EasyOperationHandleFunc m sync.RWMutex } func NewEasyOperationHandler() *EasyOperationHandler { o := &EasyOperationHandler{ IsDebug: false, SuggestWhenNotFound: false, LogSuccessAccess: true, LogFailedAccess: true, logger: func(level int, msg string, err error) { }, } o.handlerMap = make(map[string]map[zsshrpc_server.ZSshRpcMethod]EasyOperationHandleFunc) return o } func (this *EasyOperationHandler) EnableDebug() { this.IsDebug = true } func (this *EasyOperationHandler) DisableAccessSuccessLog() { this.LogSuccessAccess = false } func (this *EasyOperationHandler) DisableAccessFailLog() { this.LogFailedAccess = false } func (this *EasyOperationHandler) EnableUriSuggestWhenNotFound() { this.SuggestWhenNotFound = true } func (this *EasyOperationHandler) UseLogger(logger zsshrpc_server.SvrLogFunc) { this.logger = logger } func (this *EasyOperationHandler) HandleOperation(request zsshrpc_server.ZSshRpcOperationRequest) zsshrpc_server.ZSshRpcOperationResponse { this.m.RLock() uv, ok := this.handlerMap[request.URI] this.m.RUnlock() if ok { this.m.RLock() mv, ok := uv[request.Method] this.m.RUnlock() if ok { ereq := &EasyOpHdlRequest{ RawRequest: request, isGJsonProc: false, isErrHappend: false, isJsonProcError: false, logger: this.logger, } eresp := &EasyOpHdlResponse{ isUseRegularJson: false, isUseSimpleJson: false, isErrHappend: false, logger: this.logger, responseJson: "{}", statusCode: zsshrpc_server.ResponseStatusCode_OK, } mv(ereq, eresp) if ereq.isErrHappend { if ereq.isJsonProcError { if this.LogFailedAccess { this.logger(zsshrpc_server.SvrLogLevel_INFO, fmt.Sprintf("%s %s -> %s", zsshrpc_server.GetOperationMethodName(request.Method), request.URI, zsshrpc_server.GetResponseStatusCodeString(601), ), nil, ) } respj := simplejson.New() errj := simplejson.New() extmsgj := simplejson.New() extmsgj.Set("description", "JSON Decode Failed.") if this.IsDebug { extmsgj.Set("detail", ereq.errMsg) } errj.Set("code", 601) errj.Set("msg", zsshrpc_server.GetResponseStatusCodeString(601)) errj.Set("ext_err_msg", extmsgj) respj.Set("err", errj) jdata, err := respj.MarshalJSON() if err != nil { this.logger(zsshrpc_server.SvrLogLevel_WARNING, fmt.Sprint("Internal Error: ", err.Error()), nil, ) if this.IsDebug { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: `{"internal_fatal_error":"` + err.Error() + `"}`, } } else { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: "{}", } } } return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_JSON_DECODE_ERROR, ResponseJSON: string(jdata), } } else { if this.LogFailedAccess { this.logger(zsshrpc_server.SvrLogLevel_INFO, fmt.Sprintf("%s %s -> %s", zsshrpc_server.GetOperationMethodName(request.Method), request.URI, zsshrpc_server.GetResponseStatusCodeString(500), ), nil, ) } respj := simplejson.New() errj := simplejson.New() extmsgj := simplejson.New() extmsgj.Set("description", "Internal Error.") if this.IsDebug { extmsgj.Set("detail", ereq.errMsg) } errj.Set("code", 500) errj.Set("msg", zsshrpc_server.GetResponseStatusCodeString(500)) errj.Set("ext_err_msg", extmsgj) respj.Set("err", errj) jdata, err := respj.MarshalJSON() if err != nil { this.logger(zsshrpc_server.SvrLogLevel_WARNING, fmt.Sprint("Internal Error: ", err.Error()), nil, ) if this.IsDebug { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: `{"internal_fatal_error":"` + err.Error() + `"}`, } } else { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: "{}", } } } return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: string(jdata), } } } if eresp.isErrHappend { if this.LogFailedAccess { this.logger(zsshrpc_server.SvrLogLevel_INFO, fmt.Sprintf("%s %s -> %s", zsshrpc_server.GetOperationMethodName(request.Method), request.URI, zsshrpc_server.GetResponseStatusCodeString(500), ), nil, ) } respj := simplejson.New() errj := simplejson.New() extmsgj := simplejson.New() extmsgj.Set("description", "Internal Error.") if this.IsDebug { extmsgj.Set("detail", eresp.errMsg) } errj.Set("code", 500) errj.Set("msg", zsshrpc_server.GetResponseStatusCodeString(500)) errj.Set("ext_err_msg", extmsgj) respj.Set("err", errj) jdata, err := respj.MarshalJSON() if err != nil { this.logger(zsshrpc_server.SvrLogLevel_WARNING, fmt.Sprint("Internal Error: ", err.Error()), nil, ) if this.IsDebug { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: `{"internal_fatal_error":"` + err.Error() + `"}`, } } else { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: "{}", } } } return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: string(jdata), } } else { if eresp.isUseSimpleJson { ejd, err := eresp.simpleJson.MarshalJSON() if err != nil { if this.LogFailedAccess { this.logger(zsshrpc_server.SvrLogLevel_INFO, fmt.Sprintf("%s %s -> %s", zsshrpc_server.GetOperationMethodName(request.Method), request.URI, zsshrpc_server.GetResponseStatusCodeString(500), ), nil, ) } respj := simplejson.New() errj := simplejson.New() extmsgj := simplejson.New() extmsgj.Set("description", "Internal Error.") if this.IsDebug { extmsgj.Set("detail", err) } errj.Set("code", 500) errj.Set("msg", zsshrpc_server.GetResponseStatusCodeString(500)) errj.Set("ext_err_msg", extmsgj) respj.Set("err", errj) jdata, err := respj.MarshalJSON() if err != nil { this.logger(zsshrpc_server.SvrLogLevel_WARNING, fmt.Sprint("Internal Error: ", err.Error()), nil, ) if this.IsDebug { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: `{"internal_fatal_error":"` + err.Error() + `"}`, } } else { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: "{}", } } } return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: string(jdata), } } eresp.responseJson = string(ejd) } } if this.LogSuccessAccess { this.logger(zsshrpc_server.SvrLogLevel_INFO, fmt.Sprintf("%s %s -> %s", zsshrpc_server.GetOperationMethodName(request.Method), request.URI, zsshrpc_server.GetResponseStatusCodeString(eresp.statusCode), ), nil, ) } return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: eresp.statusCode, ResponseJSON: eresp.responseJson, } } else { if this.LogFailedAccess { this.logger(zsshrpc_server.SvrLogLevel_INFO, fmt.Sprintf("%s %s -> %s", zsshrpc_server.GetOperationMethodName(request.Method), request.URI, zsshrpc_server.GetResponseStatusCodeString(405), ), nil, ) } respj := simplejson.New() errj := simplejson.New() extmsgj := simplejson.New() methodlist := make([]string, 0) for key, _ := range uv { methodlist = append(methodlist, zsshrpc_server.GetOperationMethodName(key)) } extmsgj.Set("description", "Method '"+zsshrpc_server.GetOperationMethodName(request.Method)+"' Not Allowed With URI '"+ request.URI+"'.", ) extmsgj.Set("allowed_methods", methodlist) errj.Set("code", 405) errj.Set("msg", zsshrpc_server.GetResponseStatusCodeString(405)) errj.Set("ext_err_msg", extmsgj) respj.Set("err", errj) jdata, err := respj.MarshalJSON() if err != nil { this.logger(zsshrpc_server.SvrLogLevel_WARNING, fmt.Sprint("Internal Error: ", err.Error()), nil, ) if this.IsDebug { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: `{"internal_fatal_error":"` + err.Error() + `"}`, } } else { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: "{}", } } } return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_METHOD_NOT_ALLOWED, ResponseJSON: string(jdata), } } } else { if this.LogFailedAccess { this.logger(zsshrpc_server.SvrLogLevel_INFO, fmt.Sprintf("%s %s -> %s", zsshrpc_server.GetOperationMethodName(request.Method), request.URI, zsshrpc_server.GetResponseStatusCodeString(404), ), nil, ) } respj := simplejson.New() errj := simplejson.New() extmsgj := simplejson.New() extmsgj.Set("description", "URI '"+request.URI+"' Not Defined In RPC Server.", ) if this.SuggestWhenNotFound { urlsuggestlist := make([]string, 0) for key, _ := range this.handlerMap { urlsuggestlist = append(urlsuggestlist, key) } extmsgj.Set("suggest_uri", urlsuggestlist) } errj.Set("code", 404) errj.Set("msg", zsshrpc_server.GetResponseStatusCodeString(404)) errj.Set("ext_err_msg", extmsgj) respj.Set("err", errj) jdata, err := respj.MarshalJSON() if err != nil { this.logger(zsshrpc_server.SvrLogLevel_WARNING, fmt.Sprint("Internal Error: ", err.Error()), nil, ) if this.IsDebug { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: `{"internal_fatal_error":"` + err.Error() + `"}`, } } else { return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_INTERNAL_ERROR, ResponseJSON: "{}", } } } return zsshrpc_server.ZSshRpcOperationResponse{ StatusCode: zsshrpc_server.ResponseStatusCode_NOT_FOUND, ResponseJSON: string(jdata), } } } func (this *EasyOperationHandler) AddHandler(uri string, method zsshrpc_server.ZSshRpcMethod, handler EasyOperationHandleFunc) { this.m.Lock() defer this.m.Unlock() uv, ok := this.handlerMap[uri] if ok { uv[method] = handler } else { nuv := make(map[zsshrpc_server.ZSshRpcMethod]EasyOperationHandleFunc) nuv[method] = handler this.handlerMap[uri] = nuv } }