初步简化safe_guard

This commit is contained in:
sjcsjc123 2023-07-13 17:39:26 +08:00
parent 4cb117232d
commit 9845a661f6
12 changed files with 392 additions and 0 deletions

View File

@ -0,0 +1,17 @@
package main
import (
"net/http"
"rpc_safe_guard_01/pkg/handler"
"rpc_safe_guard_01/pkg/otto"
)
func main() {
otto.InitOtto()
http.HandleFunc("/", handler.Handler)
err := http.ListenAndServe("localhost:8081", nil)
if err != nil {
panic(err)
}
}

16
go.mod Normal file
View File

@ -0,0 +1,16 @@
module rpc_safe_guard_01
go 1.20
require (
github.com/robertkrimen/otto v0.2.1
github.com/stretchr/testify v1.8.1
)
require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/text v0.4.0 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

23
go.sum Normal file
View File

@ -0,0 +1,23 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robertkrimen/otto v0.2.1 h1:FVP0PJ0AHIjC+N4pKCG9yCDz6LHNPCwi/GKID5pGGF0=
github.com/robertkrimen/otto v0.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//farB5FlRY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

19
pkg/handler/excutor.go Normal file
View File

@ -0,0 +1,19 @@
package handler
import (
"rpc_safe_guard_01/pkg/interpreter"
"rpc_safe_guard_01/pkg/okapi"
)
func Execute(req okapi.Request) (string, error) {
vm := interpreter.GetInstance()
value, err := vm.Run(req.Body.Params["code"])
if err != nil {
return "", err
}
data, err := value.ToString()
if err != nil {
return "", err
}
return data, nil
}

36
pkg/handler/handler.go Normal file
View File

@ -0,0 +1,36 @@
package handler
import (
"net/http"
"rpc_safe_guard_01/pkg/okapi"
"strings"
)
func Handler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}
contentType := r.Header.Get("Content-Type")
if !strings.Contains(contentType, "application/json") {
http.Error(w, "Unsupported media type", http.StatusUnsupportedMediaType)
return
}
var req okapi.Request
err := req.Decode(r)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
data, err := Execute(req)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Write([]byte(data))
}

16
pkg/interpreter/otto.go Normal file
View File

@ -0,0 +1,16 @@
package interpreter
import (
"github.com/robertkrimen/otto"
"sync"
)
var instance *otto.Otto
var once sync.Once
func GetInstance() *otto.Otto {
once.Do(func() {
instance = otto.New()
})
return instance
}

47
pkg/okapi/okapi.go Normal file
View File

@ -0,0 +1,47 @@
package okapi
import (
"bytes"
"encoding/json"
"io"
"net/http"
)
type Request struct {
AppKey string
ApiName string
ApiVersion string
Body RequestBody
}
type RequestBody struct {
OaSessionID string `json:"oa-session-id,omitempty"`
OaAppMarketID string `json:"oa-app-market-id,omitempty"`
OaAppVersion string `json:"oa-app-version,omitempty"`
OaDeviceID string `json:"oa-device-id,omitempty"`
OaSign string `json:"oa-sign,omitempty"`
Timestamp string `json:"timestamp,omitempty"`
Params map[string]interface{} `json:"params,omitempty"`
}
func (req *Request) Decode(r *http.Request) error {
reqBody, err := io.ReadAll(r.Body)
if err != nil {
return err
}
// Restore the io.ReadCloser to its original state
r.Body = io.NopCloser(bytes.NewBuffer(reqBody))
if err = r.ParseForm(); err != nil {
return err
}
req.AppKey = r.Form.Get("appkey")
req.ApiName = r.Form.Get("api")
req.ApiVersion = r.Form.Get("version")
err = json.Unmarshal(reqBody, &req.Body)
if err != nil {
return err
}
return nil
}

47
pkg/okrpc/okrpc.go Normal file
View File

@ -0,0 +1,47 @@
package okrpc
import (
"bytes"
"encoding/json"
"io"
"net/http"
)
const (
RpcRequestUrl = "http://127.0.0.1:8080"
)
type Request struct {
Class string `json:"class"`
Method string `json:"method"`
Args []interface{} `json:"args"`
}
type Response struct {
Success bool `json:"success"`
ErrorCode string `json:"errorCode,omitempty"`
ErrorMessage string `json:"errorMessage,omitempty"`
Data interface{} `json:"data"`
}
func (r Request) SendRpcRequest() (string, error) {
data, err := json.Marshal(r)
if err != nil {
return "", err
}
request, err := http.NewRequest("POST", RpcRequestUrl, bytes.NewBuffer(data))
if err != nil {
return "", err
}
request.Header.Set("Content-Type", "application/json; charset=utf-8")
client := &http.Client{}
resp, err := client.Do(request)
if err != nil {
return "", err
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}

40
pkg/okrpc/okrpc_test.go Normal file
View File

@ -0,0 +1,40 @@
package okrpc
import (
"encoding/json"
"fmt"
"github.com/stretchr/testify/assert"
"testing"
)
func TestSendRpcRequest(t *testing.T) {
request := Request{
Class: "rpcLinker.SbxQitListService",
Method: "executeChain",
}
request.Args = append(request.Args, "1")
arg0 := make(map[string]interface{})
arg0["pagination"] = make(map[string]interface{})
arg0["pagination"].(map[string]interface{})["current"] = 1
arg0["pagination"].(map[string]interface{})["pageSize"] = 10
arg0["pagination"].(map[string]interface{})["returnAll"] = false
request.Args = append(request.Args, arg0)
resp, err := request.SendRpcRequest()
assert.Nil(t, err)
t.Log(resp)
}
func TestUnmarshal(t *testing.T) {
str := `[{'pagination':{'returnAll':false,'current':1,'pageSize':10}},1]`
var data []interface{}
err := json.Unmarshal([]byte(str), &data)
if err != nil {
fmt.Println("JSON unmarshaling failed:", err)
return
}
fmt.Printf("%#v\n", data)
}

73
pkg/otto/otto.go Normal file
View File

@ -0,0 +1,73 @@
package otto
import (
"encoding/json"
"errors"
"github.com/robertkrimen/otto"
"rpc_safe_guard_01/pkg/interpreter"
"rpc_safe_guard_01/pkg/okrpc"
)
const (
RpcServiceName = "rpcRequest"
RpcName = "gw"
ExitName = "exit"
)
var ErrorCodeMap = map[int]string{
10001: "rpc request error",
}
func InitOtto() {
// 注册通用方法到otto里
instance := interpreter.GetInstance()
err := instance.Set(RpcName, map[string]interface{}{
RpcServiceName: call,
ExitName: exit,
})
if err != nil {
panic(err)
}
}
func call(call otto.FunctionCall) otto.Value {
if len(call.ArgumentList) != 2 {
value, _ := otto.ToValue(errors.New("argument invalid"))
return value
}
rpcName := call.Argument(0)
param := call.Argument(1)
p, err := param.ToString()
if err != nil {
value, _ := otto.ToValue(err)
return value
}
var args []interface{}
err = json.Unmarshal([]byte(p), &args)
if err != nil {
value, _ := otto.ToValue(err)
return value
}
var req okrpc.Request
req.Class = rpcName.String()
req.Method = "executeChain"
req.Args = args
resp, err := req.SendRpcRequest()
if err != nil {
value, _ := otto.ToValue(err)
return value
}
value, _ := otto.ToValue(resp)
return value
}
func exit(call otto.FunctionCall) otto.Value {
code, err := call.Argument(0).ToInteger()
if err != nil {
value, _ := otto.ToValue(errors.New("the code is not number"))
return value
}
// 此处传入Api Error Code先用map代替
value, _ := otto.ToValue(ErrorCodeMap[int(code)])
return value
}

44
question.md Normal file
View File

@ -0,0 +1,44 @@
## 1. 简化思路
例如:
```javascript
// 1. 检查用户名是否已经注册
hasUser = rpc.call("com.swallow.user.checkUserName", user.name)
if (hasUser != null) {
rpc.error("code", "message")
}
// 2. 检查手机号是否已经注册
hasPhone = rpc.call("com.swallow.user.checkPhoneNumber", user.phoneNumber)
if (hasPhone != null) {
rpc.error("code", "message")
}
// 3. 创建用户
create = rpc.call("com.swallow.user.create", user)
if (create) {
rpc.success({ "data": create })
}
```
目前的简化思路就是我在后台只注册rpc参数并给rpc注册call/error等方法配置文件全部弃掉
## 2、call函数使用
- 第一个参数是要调用的rpc名字可以来自于rpc linker也可以来自于java service
- 第二个参数是写成类似于这样的来接受0个或多个参数的请求体请求体将会传递给rpc方法的请求参数
```javascript
arg = {
"name": "test",
"age": 12,
"other": "ssss"
}
rpc.call("com.swallow.user.create", arg)
```
## 3、条件限定
- go后台拿到rpc响应后是不是还需要根据条件限定对响应进行校验
- 例如HTML或者APP传递条件给我username != null我需要根据这个条件加个判断再返回响应给js。
## 4、前台传递的条件是单个还是多个

View File

@ -0,0 +1,14 @@
POST http://localhost:8081/okapi3?api=rpcLinker.SbxOrderSearchService&version=1.0&appkey=c94ec1fc-58c1-41c6-9980-ead078ae2c97
Content-Type: application/json
{
"oa-session-id": "7E2532FF3A72D64A91B9810EBBDF2441",
"oa-app-market-id": "678",
"oa-app-version": "1.0",
"oa-device-id": "1911151415",
"oa-sign": "1a6f78424a4874bdfb3ee716c372e547",
"timestamp": "1686919817370370",
"params": {
"code": "gw.rpcRequest('rpcLinker.SbxQitListService', '[{\"pagination\":{\"returnAll\":false,\"current\":1,\"pageSize\":10}},1]')"
}
}