Closed3

【Go】oapi-codegenメモ

yagi_engyagi_eng

これ

openapi.ymlから構造体やルーティング、簡単なバリデーションを自動生成できる優れもの
https://github.com/deepmap/oapi-codegen

参考

  • 基本的に以下の記事を参考にすればOK
  • 細かい点のみこのスクラップで補足

https://future-architect.github.io/articles/20200701/

構造体の自動生成

こんな感じで自動生成される

// Type definition for component schema "Error"
type Error struct {
    Code    int32  `json:"code"`
    Message string `json:"message"`
}

// Type definition for component schema "NewPet"
type NewPet struct {
    Name string  `json:"name"`
    Tag  *string `json:"tag,omitempty"`
}

// Type definition for component schema "Pet"
type Pet struct {
    // Embedded struct due to allOf(#/components/schemas/NewPet)
    NewPet
    // Embedded fields due to inline allOf schema
    Id int64 `json:"id"`
}

// Type definition for component schema "Pets"
type Pets []Pet

controller相当部分の自動生成

以下のようなinterfaceが自動生成されるので、これを実装していく

type ServerInterface interface {
    //  (GET /pets)
    FindPets(ctx echo.Context, params FindPetsParams) error
    //  (POST /pets)
    AddPet(ctx echo.Context) error
    //  (DELETE /pets/{id})
    DeletePet(ctx echo.Context, id int64) error
    //  (GET /pets/{id})
    FindPetById(ctx echo.Context, id int64) error
}

notes

  • 上記interfaceを実装するメソッドの返り値
    • c.JSON (error型)などをreturnすればOK
    • つまり、responseのbindはしてくれない
  • openapi.ymlのnumber型プロパティはformat: doubleを指定すると、float64型になる
    • formatを指定しないと、float32型になる
  • openapi.ymlでnumber型にrequierdを指定した場合、0は弾かれるか?
  • バリデーションはrequierdと型チェックくらいしかしてくれず、他の細かいバリデーションは自分で実装する必要ある
  • 自動生成されたバリデーション部分は、エラーを返す時にstring型でエラー内容を返している
  • 自動生成コードによるparameterのbind
  • oapi-codegenについて、クライアント(HTTPサーバにリクエストを送るやつ)も自動生成してくれる
    • APIの結合テストとかに使えそう
yagi_engyagi_eng

OapiRequestValidator調査

  • openapi.ymlを基にバリデーションをしてくれる
  • GETと同じ内容をバリデーションしてくれる
    • requierdと型チェックはしてくれる
  • minimum, lengthなどはチェックしてくれない
  • POST/PUTメソッドにおいて、requestBodyの構造体タグにはqueryではなくjsonを使う必要がある
    • 自動生成されたコードではjsonタグを使っているので特に気にする必要なし
  • kin-openapiについて、リポジトリやコードを読み込めばもっと色々機能ありそう
yagi_engyagi_eng

https://github.com/OpenAPITools/openapi-generator
で生成されるコードはなんか微妙。Go用の方が使い勝手良い

GETのpath/query paramはcontroller内部で受け取りされる。構造体は生成されない

// GetXXX - Get XXX
func (c *XXXApiController) GetXXX(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	idParam, err := parseInt32Parameter(params["id"], true)
	if err != nil {
		c.errorHandler(w, r, &ParsingError{Err: err}, nil)
		return
	}

	result, err := c.service.GetXXX(r.Context(), idParam)
	// If an error occurred, encode the error with the status code
	if err != nil {
		c.errorHandler(w, r, err, &result)
		return
	}
	// If no error, encode the body and the result code
	EncodeJSONResponse(result.Body, &result.Code, w)

}

オプションの設定がCLIのhelpと以下ドキュメントで乖離してる

openapi-generator-cli config-help -g go-server


CONFIG OPTIONS

        addResponseHeaders
            To include response headers in ImplResponse (Default: false)

        enumClassPrefix
            Prefix enum with class name (Default: false)

        featureCORS
            Enable Cross-Origin Resource Sharing middleware (Default: false)

        hideGenerationTimestamp
            Hides the generation timestamp when files are generated. (Default: true)

        packageName
            Go package name (convention: lowercase). (Default: openapi)

        packageVersion
            Go package version. (Default: 1.0.0)

        router
            Specify the router which should be used. (Default: mux)
                mux - mux
                chi - chi

        serverPort
            The network port the generated server binds to (Default: 8080)

        sourceFolder
            source folder for generated code (Default: go)

https://openapi-generator.tech/docs/generators/go-server/#config-options

このスクラップは2021/11/30にクローズされました