プラグイン


Goa プラグイン を使用すると、 新しい DSL と付随するジェネレーターを作成できます。 これらは最終的な生成物をレンダリングする前に実行されるため、 Goa コードジェネレーターによって公開されるテンプレートを変更でき、 それによって、任意の DSL から新しい種類の出力が生成されます。

Goa プラグイン リポジトリ には、 Goa プラグインのパブリックセットが含まれています。 使用方法については、すべてのプラグインに含まれる README を参照してください。

独自プラグインの構築

いくつか異なることをおこなうために、プラグインを使用することが出来ます:

  • プラグインは、既存の Goa DSL とともに使用される独自の DSL を追加できます。 プラグイン DSL は、まったく異なるコードを生成したり、Goa コードジェネレーターによって生成された既存のコードを変更したりできます。

  • プラグインは、GenerateFunc を提供して、 Goa が生成したファイルを変更したり、新しいファイルを生成して最終的な生成物として返したりできます。

type GenerateFunc func(genpkg string, roots []eval.Root, files []*File) ([]*File, error)
  • プラグインは、コードが生成される前にデザインを変更するために、 PrepareFunc を提供する場合があります。
type PrepareFunc func(genpkg string, roots []eval.Root) error

プラグインは、 RegisterPlugin 関数、 RegisterPluginFirst 関数、 もしくは RegisterPluginLast 関数 を使用してプラグイン自身を登録します。

CORS プラグイン

組み込みプラグインの1つは、CORS プラグイン で、 このプラグインは HTTP エンドポイントで CORS プロパティを定義する機能を追加し、 対応する式を使用して API に対して CORS を実装するコードを生成します。

CORS プラグインは、以下に示すようにデザインで 使用できる独自の DSL を追加します:

package design

import (
	. "goa.design/goa/v3/dsl"
	cors "goa.design/plugins/v3/cors/dsl"
)

var _ = Service("calc", func() {
	Description("The calc service exposes public endpoints that defines CORS policy.")
	// CORS DSL を利用して CORS ポリシーを追加します
	cors.Origin("/.*localhost.*/", func() {
		cors.Headers("X-Shared-Secret")
		cors.Methods("GET", "POST")
		cors.Expose("X-Time", "X-Api-Version")
		cors.MaxAge(100)
		cors.Credentials()
	})

	Method("multiply", func() {
		Description("Multiply multiplies up the two integer parameters and returns the results.")
		Payload(func() {
			Attribute("a", Int, func() {
				Description("Left operand")
			})
			Attribute("b", Int, func() {
				Description("Right operand")
			})
			Required("a", "b")
		})
		Result(Int)
		HTTP(func() {
			GET("/multiply/{a}/{b}")
			Response(StatusOK)
		})
	})
})

上記のデザインでは、calc サービスで定義されたすべてのエンドポイントに CORS ポリシーを設定します。

CORS プラグインは、Goa codegen パッケージの RegisterPlugin 関数を呼び出すことで自身を登録し、 GenerateFunc 型を実装する独自のコードジェネレーターを追加します。

package cors

import (
	"goa.design/goa/v3/codegen"
	"goa.design/goa/v3/eval"
)

func init() {
	codegen.RegisterPlugin("cors", "gen", nil, Generate)
}

// Generate は、プリフライトリクエストを処理するサーバーコードを生成し、
// 適切な CORS ヘッダーで HTTP レスポンスを更新します。
func Generate(genpkg string, roots []eval.Root, files []*codegen.File) ([]*codegen.File, error) {
...
}
// cors/dsl/cors.go

package dsl

// CORSプラグインのコードジェネレーターを登録する
import _ "goa.design/plugins/v3/cors"

このジェネレーターは、CORS エンドポイントをマウントすることにより、 プリフライトリクエストを処理するために、生成された HTTP サーバーコードを変更します。

次に、Goa コード生成アルゴリズムは、生成された HTTP サーバーパッケージを変更する関数を呼び出します。