簡単にRESTサーバ・GraphQLサーバを立ち上げる

前回の投稿 [JavascriptのImportとVueのコンポーネントを使えるようになってみる]( https://qiita.com/poruruba/items/92164ca0fe7057199adf) に引き続き、テンプレート環境の使い方をまとめておきます。
今回はサーバ側ということで、RESTサーバとGraphQLサーバの立ち上げ方を備忘録としてまとめておきます。

テンプレートは以下のGitHubに上げてあります。

poruruba/express_template
https://github.com/poruruba/express_template

※たびたび機能追加しているので、ここに記載していない機能も入っている可能性大です。

#RESTサーバを立ち上げる

api/controllers/の配下に、適当なフォルダを作成し、index.jsとswagger.yamlを作成します。

index.jsは通常は、API Gateway経由でLambdaに転送されたときに似せています。

(i) JSON/POST呼び出しの場合

受け付けた呼び出しは、index.jsのexports.handlerで受け取ることができます。BODYに指定された引数を取得するには、以下のようにします。

```js
exports.handler = async (event, context, callback) => {
	var body = JSON.parse(event.body);
```

(ii) GET呼び出しの場合

同様に、受け付けた呼び出しは、index.jsのexports.handlerで受け取ることができます。QueryStringの引数を取得するには、以下のようにします。

```js
exports.handler = async (event, context, callback) => {
	var params = event.queryStringParameters;
```

レスポンスは、application/jsonで返すことが多いので、ヘルパー関数を用意しています。
こんな感じで返します。

```js
	return new Response({ message: 'Hello World' });
```

もし、バイナリで返す場合は以下のようにします。

```js
	return new BinResponse("application/octet-stream", buffer);
```

もし、テキストで返す場合は以下のようにします。

```js
	return new TextResponse("text/html", str);
```

リダイレクトさせたい場合には、以下のようにします。

```js
	return new Redirect(url);
```

swagger.yamlには、エンドポイントを定義します。Swagger2.0の定義のうちの、pathsとdefinitionsを定義します。（ただし、実際に参照しているのは、エンドポイント名だけですが。。。）
api/controllers/フォルダ配下にサンプルを置いていますので参考にしてください。

いくつかオプション設定できるようにしました。

〇オプションタグ: x-handler

```
　x-handler: 任意
```

通常は、エンドポイントが呼ばれると、index.jsのexports.handlerが呼び出されますが、このhandlerじゃない関数名で呼ばれたい場合にはここで指定します。
認証の検証をするわけではないのですが、パースして、index.js に結果を渡してあげます。

〇オプションタグ: security

```
security:
- basicAuth: []
- tokenAuth: []
- apikeyAuth: []
- jwtAuth: []
```

basicAuth ： クライアントIDとクライアントシークレットがBase64でエンコードされた認証情報です。
　Authorization: basic [Bases64Encode(‘client_id’:’client_secret’)]

tokenAuth：OpenID ConnectやOAuth2のトークンを指定する場合の認証情報です。
　Authorization: bearer [Token]

apikeyAuth：APIキーを使った認証情報です。
　X-API-KEY：[APIKey]

jwtAuth：GCPのCloud Endpoint認証のための認証情報です。
　Authorization: bearer [Token]

Authorizationヘッダが設定されて呼び出される場合に指定します。req.requestContext に解析結果が設定されます。

〇オプションタグ: x-functype

```
x-functype: (express|empty|normal|alexa|lambda)
```

index.jsの呼び出し型を指定します。通常はnormalで、API Gateway経由でlambdaが呼ばれたときと同じようにふるまいますが、型を変えたい場合に指定します。

一応、忘れないように。Multipartでファイルを送るときは以下の指定にします。

〇file(multipart/form-data)の処理

```
parameters:
- in: formData
  type: file
  name: 任意
```

event.files.upfile[0] に受信したバイナリが格納されます。

```npm run start```で起動させると、api/controllers/配下の各フォルダにあるswagger.yamlを検索し、自動的にエンドポイントの定義を読み出して、エンドポイントを立ち上げるようにしています。

また、https://localhost:10080/swagger にアクセスすると、Yaml形式のSwagger定義をテキストで取得できます。
なので、以下のようなSwaggerエディタから、エンドポイントを可視化したり試しに呼び出しができます。

Swagger-Editor
　https://editor.swagger.io/

swagger-api/swagger-editor
　https://github.com/swagger-api/swagger-editor

File ⇒ Import URL で表示されるダイアログボックスに、立ち上げた上記のURLを入力してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/6f62c249-7295-9973-5c4c-0616bf1daba9.png)
 
```npm run swagger```を実行することでも、各フォルダのswagger.yamlを結合してapi/swagger/swagger.yaml というファイルを出力することもできます。

#GraphQLサーバの立ち上げ

api/controllers/の配下に、適当なフォルダを作成し、index.jsとschema.graphqlを作成します。

index.jsは以下のような感じで引数を取得し、schema.graphqlで定義したレスポンスに従って返すように実装します。

以下例です。

```
exports.handler = async(parent, args, context, info) =>{
	console.log("args", JSON.stringify(args));
	console.log("path", info.path);

	return "Hello World";
};
```

schema.graphqlは、もちろんGraphQLです。
※Subscriptionはまだ実装していませんので、書いても動きません。。。

例えばこんな感じです。


```
type Query {
  hello(message: String, param: Int): String
}
```

アノテーションでオプションを定義できるようにしています。

@endpointアノテーション

```
schema @endpoint(endpoint: "/mygraphql"){
  query: Query,
}
```

上記のアノテーションを記載しておくと、指定されたエンドポイント名でGraphQLのエンドポイントを立ち上げます。
上記の例では、エンドポイントは以下のようになります。

　http://localhost:10080/mygraphql

上記のアノテーションがない場合には、エンドポイントは自動的に以下のように割り当たります。

　http://localhost:10080/【フォルダ名】

@handlerアノテーション

```
type Query @handler(handler: "fulfillment", type: "lambda"){
  hello(param1: String, param2: Int): MyModelType
  test: [ToDo]
}
```

通常は、index.jsの呼び出しは、express_graphqlの呼び出し形式ですが、type:lambdaとすると、AWSのAppSyncに似せることができます。

handlerの定義は、通常は、index.js のexports.handerが呼び出されますが、名前を変えたい場合に指定します。handler: fulfillmentとした場合には、以下の部分が呼び出されます。

```
exports.fulfillment = async(parent, args, context, info) =>{
```

また、GraphQLエクスプローラも立ち上がるようにしています。
http://localhost:10080/graphql をブラウザで開くと以下のようなページが表示されます。
自動で立ち上げたGraphQLのフォルダ名が表示されています。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/c8f27aa2-4970-0b2a-d178-85f61e05901b.png)

いずれかを選択すると、以下のようなGraphQLエクスプローラが立ち上がり、GraphQLのQueryやMutationの定義を確認したり、実際に実行を試すことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/23793934-bbeb-ef86-41a0-f60ac4d0df49.png)

#ヘルパー

Alexaスキル、Alexaスマートホーム、Clova、LINEボット、Slack、Dialogflowなどとつなぐのに便利なヘルパをapi/helpers/に用意しています。

今後加筆するかもしれませんが、とりあえず以下を参考にしてください。ベースがテンプレート環境ではなくSwagger-Node環境で異なるのですが、ヘルパの使い方は同じです。

　[SwaggerでLambdaのデバッグ環境を作る(1)](https://qiita.com/poruruba/items/e3a46787c79517a815f9)

#終わりに

こちらもご参考にどうぞ
　[JavascriptのImportとVueのコンポーネントを使えるようになってみる](https://qiita.com/poruruba/items/92164ca0fe7057199adf)

以上