|
@@ -0,0 +1,394 @@
|
|
|
+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
|
|
|
+ }
|
|
|
+}
|