Better validation

This commit is contained in:
Александр Кирюхин 2022-05-29 14:18:10 +03:00
parent f304a07a8c
commit 3d5463c820
No known key found for this signature in database
GPG key ID: 6DF7A2910D0699E9
2 changed files with 51 additions and 19 deletions

View file

@ -7,7 +7,6 @@ import (
"os" "os"
"os/signal" "os/signal"
"github.com/qri-io/jsonschema"
"go.neonxp.dev/jsonrpc2/rpc" "go.neonxp.dev/jsonrpc2/rpc"
"go.neonxp.dev/jsonrpc2/rpc/middleware" "go.neonxp.dev/jsonrpc2/rpc/middleware"
"go.neonxp.dev/jsonrpc2/transport" "go.neonxp.dev/jsonrpc2/transport"
@ -18,10 +17,12 @@ func main() {
rpc.WithLogger(rpc.StdLogger), rpc.WithLogger(rpc.StdLogger),
rpc.WithTransport(&transport.HTTP{Bind: ":8000", CORSOrigin: "*"}), rpc.WithTransport(&transport.HTTP{Bind: ":8000", CORSOrigin: "*"}),
) )
// Set options after constructor // Set options after constructor
validation, err := middleware.Validation(map[string]middleware.MethodSchema{ serviceSchema := `
{
"divide": { "divide": {
Request: *jsonschema.Must(`{ "request": {
"type": "object", "type": "object",
"properties": { "properties": {
"a": { "a": {
@ -33,8 +34,8 @@ func main() {
} }
}, },
"required": ["a", "b"] "required": ["a", "b"]
}`), },
Response: *jsonschema.Must(`{ "response": {
"type": "object", "type": "object",
"properties": { "properties": {
"quo": { "quo": {
@ -45,9 +46,28 @@ func main() {
} }
}, },
"required": ["quo", "rem"] "required": ["quo", "rem"]
}`), }
}, },
}) "multiply": {
"request": {
"type": "object",
"properties": {
"a": {
"type": "integer"
},
"b": {
"type": "integer"
}
},
"required": ["a", "b"]
},
"response": {
"type": "integer"
}
}
}`
validation, err := middleware.Validation(middleware.MustSchema(serviceSchema))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }

View file

@ -30,25 +30,37 @@ import (
"go.neonxp.dev/jsonrpc2/rpc" "go.neonxp.dev/jsonrpc2/rpc"
) )
type MethodSchema struct { type ServiceSchema map[string]MethodSchema
Request jsonschema.Schema
Response jsonschema.Schema func MustSchema(schema string) ServiceSchema {
ss := new(ServiceSchema)
if err := json.Unmarshal([]byte(schema), ss); err != nil {
panic(err)
}
return *ss
} }
func Validation(serviceSchema map[string]MethodSchema) (rpc.Middleware, error) { type MethodSchema struct {
Request *jsonschema.Schema `json:"request"`
Response *jsonschema.Schema `json:"response"`
}
func Validation(serviceSchema ServiceSchema) (rpc.Middleware, error) {
return func(handler rpc.RpcHandler) rpc.RpcHandler { return func(handler rpc.RpcHandler) rpc.RpcHandler {
return func(ctx context.Context, req *rpc.RpcRequest) *rpc.RpcResponse { return func(ctx context.Context, req *rpc.RpcRequest) *rpc.RpcResponse {
if rs, ok := serviceSchema[strings.ToLower(req.Method)]; ok { rs, hasSchema := serviceSchema[strings.ToLower(req.Method)]
if errResp := formatError(ctx, req.Id, rs.Request, req.Params); errResp != nil { if hasSchema && rs.Request != nil {
if errResp := formatError(ctx, req.Id, *rs.Request, req.Params); errResp != nil {
return errResp return errResp
} }
resp := handler(ctx, req)
if errResp := formatError(ctx, req.Id, rs.Response, resp.Result); errResp != nil {
return errResp
}
return resp
} }
return handler(ctx, req) resp := handler(ctx, req)
if hasSchema && rs.Response != nil {
if errResp := formatError(ctx, req.Id, *rs.Response, resp.Result); errResp != nil {
return errResp
}
}
return resp
} }
}, nil }, nil
} }