Closed9
kin-openapiのopenapi3filterの使い方を把握する
自分でopenapiを利用したvalidationをしたかった。
- request validation
- response validation
の2種類があるがそれぞれについて調べたい
いろいろ調べてみると deepmap/oapi-codegen自体ではvalidationをしておらず、getkin/kin-openapi/openapi3filterでvalidationをしているようだった。
とりあえず、この辺を観る必要がある(routersの方を観る必要がある理由は後述する)。
利用方法自体はexamplesを見れば良い
基本的には以下のような形になる。
- yamlを読み込んで、swagger objectの生成 (
openapi3.T
) - swagger objectを利用して、routes.Router objectを生成 (ここで gorillamux パッケージを利用することになる)
- (request毎に)routes.Routerの
FindRoute()
を使ってRoute objectを取得する - (request毎に) Route objectを使って
openapi3filter.RequestValidationInput
を作り、ValidationRequest()を呼ぶ - (request毎にresponseに対して)
openapi3filter.ResponseValidationInput
を作り、ValidationResponse()を呼ぶ
大まかにはこういうイメージここで routes.Router は以下のようなinterface
type Router interface {
// FindRoute matches an HTTP request with the operation it resolves to.
// Hosts are matched from the OpenAPIv3 servers key.
//
// If you experience ErrPathNotFound and have localhost hosts specified as your servers,
// turning these server URLs as relative (leaving only the path) should resolve this.
//
// See openapi3filter for example uses with request and response validation.
FindRoute(req *http.Request) (route *Route, pathParams map[string]string, err error)
}
実際の利用方法自体はdeepmap/oapi-codegenのmiddlewareなどの実装を見れば良い。
errorになったときのresponseの形状など知りたい事はあるけれど、一旦はこの辺で大丈夫そう。
net/httpのmiddlewareとして使いたい場合は、Validatorを作れば良いらしい。
とりあえず、その前に、kin-openapiの使い方に慣れる。
( :thought_balloon: openapi3.Operation
部分のところがfieldでだるかったけれど、この辺で手軽に使える程度にはreflectを空で書けるようになった)
自分で、利用するコードが書けた。
実行例
ng request ----------------------------------------
find route: /pets POST map[]
validate request is failed: *openapi3filter.RequestError
validate request: request body has an error: doesn't match the schema: Error at "/name": property "name" is missing
Schema:
{
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
}
Value:
{}
ng response ----------------------------------------
find route: /pets POST map[]
request is ok
valicate response is failed: *openapi3filter.ResponseError
validate response: response body doesn't match the schema: Error at "/id": property "id" is missing
Schema:
{
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"type": "object"
}
Value:
{}
こちらのほうが見やすいかも
ng request ----------------------------------------
find route is ok
POST /pets HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{}
validate request is failed: *openapi3filter.RequestError
validate request: request body has an error: doesn't match the schema: Error at "/name": property "name" is missing
Schema:
{
"additionalProperties": false,
"properties": {
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"name"
],
"type": "object"
}
Value:
{}
ng response ----------------------------------------
find route is ok
POST /pets HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{"name": "foo"}
request is ok
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
{}
valicate response is failed: *openapi3filter.ResponseError
validate response: response body doesn't match the schema: Error at "/id": property "id" is missing
Schema:
{
"additionalProperties": false,
"properties": {
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"tag": {
"type": "string"
}
},
"required": [
"id",
"name"
],
"type": "object"
}
Value:
{}
ok ----------------------------------------
find route is ok
POST /pets?ok=true HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{"name": "foo"}
request is ok
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
{"id":"1","name":"foo"}
response is ok
このスクラップは2023/07/03にクローズされました