Web API がエラーレスポンスを返す際にはレスポンスボディでエラーの詳細を示すのが一般的です。 goa には goa.ErrorResponse という型が組み込まれており、 controller に到達する前の処理でエラーが発生した際のレスポンスに使われています。また controller の中で goa.ErrorResponse
を使うこともできます。
controller 到達前のエラーレスポンス
例えば /foo
というエンドポイントが存在しないのに GET /foo
というリクエストが来たときには以下の形のレスポンスが返ります。
{ "id": "XXXXXXXX", "code": "not_found", "status" :404, "detail": "/foo" }
この際、レスポンスヘッダの Content-Type
は application/vnd.goa.error
となります。この値は goa.ErrorMediaIdentifier として定義されているため変更することが可能です。例えば Content-Type
を application/vnd.myservice.error
に変える場合は以下のコードを main
パッケージに追加します。
package main import ( "github.com/goadesign/goa" ) func init() { // Change the media type identifier used for error responses. goa.ErrorMediaIdentifier = "application/vnd.myservice.error" }
controller が返すエラーレスポンス
goa.ErrorResponse
には、対応する design 定義として design.ErrorMedia が用意されています。これを design の中で使うことで、あるレスポンスが goa.ErrorResponse
のフォーマットであることを明示できます。以下の例では BadRequest
に ErrorMedia
を指定することで、不正なリクエストが来たときのエラーレスポンスが goa.ErrorResponse
のフォーマットであることを表しています。
Response(BadRequest, ErrorMedia)
controller の実装では ctx.BadRequest()
を呼び出すことで Bad Request
を返却することができます。その際、引数に *goa.ErrorResponse
を渡すとそれがレスポンスボディに設定されます。
ctx.BadRequest(&goa.ErrorResponse{
Detail: "this is a error message",
})
こちらの Content-Type
も application/vnd.goa.error
ですが、controller 到達前のエラーレスポンスとは違い design.ErrorMedia.Identifier が参照されています。このフィールドには design.ErrorMediaIdentifier が設定されているため、まず design.ErrorMediaIdentifier
を変更した上で design.ErrorMedia.Identifier
に再設定しておくことで実際の Content-Type
を変更することができます。
package design import ( "github.com/goadesign/goa/design" ) func init() { // Change the media type identifier used for error responses. design.ErrorMediaIdentifier = "application/vnd.myservice.error" design.ErrorMedia.Identifier = design.ErrorMediaIdentifier }
Swagger UI
goa は Swagger 定義を出力できるので Swagger UI と組み合わせて使われることも多いと思います。しかし application/vnd.goa.error
のようにサフィックスが付いていない形式だと Try it out
ボタンでリクエストを試すときにエラーレスポンスが Unknown response type
となり表示されません。
これを表示させるには、プロジェクトに以下のコードを追加して Content-Type
をサフィックス付きの application/vnd.goa.error+json
に変更します。
package main import ( "github.com/goadesign/goa" ) func init() { // Change the media type identifier used for error responses. goa.ErrorMediaIdentifier = goa.ErrorMediaIdentifier + "+json" }
package design import ( "github.com/goadesign/goa/design" ) func init() { // Change the media type identifier used for error responses. design.ErrorMediaIdentifier = design.ErrorMediaIdentifier + "+json" design.ErrorMedia.Identifier = design.ErrorMediaIdentifier }
これで Swagger UI でもレスポンスが表示されるようになります。