Serverless Framework で 自身のAPIのURLを取得したい

### はじめに

Serverless FrameworkでAPI Gatewayを利用した際に
死活監視やなんらかの目的で
内部的にAPIを呼び出したい場合があるかと思います。

ただ、デプロイされたあとにURLを確認し
Lambdaの環境変数に・・・などはちょっと面倒くさいので
serverless.yml内だけで設定できないかやってみました。

### customにてURLを生成

本題部分です、API Gatewayで生成されるURLを文字連結します。
これでAPI GatewayのURLが生成できます。

``` yml
custom:
  region: ap-northeast-1
  stage: ${opt:stage,"default"}
  my_url:
    {
      "Fn::Join":
        [
          "",
          [
            "https://",
            { "Ref": "ApiGatewayRestApi" },
            ".execute-api.${self:custom.region}.amazonaws.com/${self:custom.stage}/",
          ],
        ],
    }

```

### customで作成したURLをLambdaのenvironmentに設定

折角なので実際にAPIを叩いてみます。
※言語はnodeを前提として記述してます。

APIを叩いてくれる`shikatsukannshi`と
`shikatsukannshi`に叩かれる`tergetA`,`tergetB`を作成します。

`shikatsukannshi`が30分に1回立ち上がって`tergetA`,`tergetB`にアクセスするような
感じで作成しています。

```yml
functions:
  shikatsukannshi:
    handler: shikatu/handler.main
    environment:
      MY_URL: ${self:custom.my_url}
    events:
      - schedule: rate(30 minutes)
  tergetA:
    handler: api/handler.main
    environment:
      MY_NAME: A
    events:
      - http:
          path: target/a
          method: get
  tergetB:
    handler: api/handler.main
    environment:
      MY_NAME: B
    events:
      - http:
          path: target/b
          method: get
```

これで`shikatsukannshi`Lambdaの環境変数MY_URL内に
自身と紐づくAPI GatewayのURLが入力されるはずです。

serverless.yml全体としては以下のようなものを作成しました。


```yml
service: qiita-sample

custom:
  region: ap-northeast-1
  stage: ${opt:stage,"default"}
  my_url:
    {
      "Fn::Join":
        [
          "",
          [
            "https://",
            { "Ref": "ApiGatewayRestApi" },
            ".execute-api.${self:custom.region}.amazonaws.com/${self:custom.stage}/",
          ],
        ],
    }

provider:
  name: aws
  runtime: nodejs12.x
  memorySize: 128
  region: ${self:custom.region}

functions:
  shikatsukannshi:
    handler: shikatu/handler.main
    environment:
      MY_URL: ${self:custom.my_url}
    events:
      - schedule: rate(30 minutes)
  tergetA:
    handler: api/handler.main
    environment:
      MY_NAME: A
    events:
      - http:
          path: target/a
          method: get
  tergetB:
    handler: api/handler.main
    environment:
      MY_NAME: B
    events:
      - http:
          path: target/b
          method: get

```

### apiと監視用Lambdaの作成

ますはAPIから
環境変数から自分の名前を取得して返すだけのAPI

```api/handler.js
module.exports.main = async (event) => {
    return {
        body: 'Qiitaサンプル:' + process.env['MY_NAME'],
        statusCode: 200
    }
}
```

そして監視用のLambda
こっちもリクエストを投げ結果をログに出すだけのもの

```shikatu/handler.js
module.exports.main = (event) => {
    const request = require("request");
    const url = process.env['MY_URL']

    // 監視A
    request.get({
        url: url + 'target/a'
    }, function (error, response, body) {
        console.log(body);
    });

    // 監視B
    request.get({
        url: url + 'target/b'
    }, function (error, response, body) {
        console.log(body);
    });
}
```

### 結果確認

デプロイしログを確認します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485089/fcc35911-1488-d7d2-9505-495d3d9babd9.png)

無事APIへアクセスできているようです。