Terraformを使用して、API Gatewayでrobots.txtを返す

CTO室の尾崎です。
最近は、インフラの構成や設定をコード化するIaCツールがいくつかありますが、
今回は、Terraformを使用して、API Gatewayで`robots.txt`を返すプログラムを紹介します。

API Gateway、Lambdaなどを使ってサーバレスな構成でAPIやWebページを公開する際、
検索エンジンにサイトマップなど正しくサイトをクロールさせたい、あるいは、クロール不要なページが引っかかってほしくないなどあると思います。

そんな時には、`robots.txt`をWebページに設置して、さまざまな検索エンジンのクローラーに対して指示することができます。
`robots.txt`はWebページのクローラーに対する指示を記述するためのファイルです。
別途Lambda関数を定義して、`robots.txt`を返すこともできるのですが、
今回はAPI Gatewayのみで`robots.txt`を返す手順をご紹介します。
`robots.txt`の詳細な仕様については以下をご参照ください。
https://developers.google.com/search/docs/crawling-indexing/robots/intro?hl=ja


### Terraformの環境

TerraformはApple MacBook Air（M2）の環境で以下のバージョンで動作確認しました。

```zsh
$ terraform -v
Terraform v1.7.4
on linux_arm64
+ provider registry.terraform.io/hashicorp/archive v2.4.2
+ provider registry.terraform.io/hashicorp/aws v5.37.0
```
### API Gatewayの作成

今回は、TerraformでAPI Gatewayを定義しています。`apigateway.tf`というファイルを作成し、次のように記述します。

```hcl
resource "aws_api_gateway_rest_api" "my_api" {
  name        = "my-api"
  description = "My API Gateway"

  endpoint_configuration {
    types = ["REGIONAL"]
  }
}

resource "aws_api_gateway_resource" "robots" {
  rest_api_id = aws_api_gateway_rest_api.my_api.id
  parent_id   = aws_api_gateway_rest_api.my_api.root_resource_id
  path_part   = "robots.txt"
}

resource "aws_api_gateway_method" "robots_method" {
  rest_api_id   = aws_api_gateway_rest_api.api.id
  authorization = "NONE"
  http_method   = "GET"
  resource_id   = aws_api_gateway_resource.robots.id
}

resource "aws_api_gateway_method_response" "robots_response" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.robots.id
  http_method = aws_api_gateway_method.robots_method.http_method
  status_code = "200"
  response_models = {
    "text/plain" = "Empty"
  }
}

resource "aws_api_gateway_integration" "robots_integration" {
  rest_api_id             = aws_api_gateway_rest_api.api.id
  resource_id             = aws_api_gateway_resource.robots.id
  http_method             = aws_api_gateway_method.robots_method.http_method
  type                    = "MOCK"
  request_templates = {
    "application/json" = <<EOF
{"statusCode" : 200}
EOF
  }
}

resource "aws_api_gateway_integration_response" "robots_integration_response" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  resource_id = aws_api_gateway_resource.robots.id
  http_method = aws_api_gateway_method.robots_method.http_method
  status_code = aws_api_gateway_method_response.robots_response.status_code

  response_templates = {
    "text/plain" = <<EOF
User-agent: *
Disallow: /
EOF
  }
}
```

この設定では、「my-api」という名前のAPI Gatewayと、その中に`robots.txt`というパスを持つリソースをGETメソッドで作成しています。
Typeを「MOCK」にして、モック統合することにより、バックエンドにLambdaを利用することなく、API Gatewayのみでレスポンスを生成できます。
ステータスコード200 OK を返すように定義し、統合レスポンスの定義に、テキストとして、`robots.txt`の内容を記述します。
今回は、サイト全体のクロールを許可しない設定で記述しています。
このあたりは、サイトの方針に沿って書き換えていただければと思います。

```robots.txt
User-agent: *
Disallow: /
```


この構成により、GET リクエストが /robots.txt に届いたときに`robots.txt`が返るようになります。

### デプロイの設定

以上の変更をAPI Gatewayに適用するため、`apigateway.tf`にaws_api_gateway_deploymentリソースを使って以下を追記しデプロイできるようにします。

```hcl
resource "aws_api_gateway_deployment" "my_api_deployment" {
  depends_on = [
    aws_api_gateway_integration.robots_integration,
    aws_api_gateway_method.robots_method
  ]

  rest_api_id = aws_api_gateway_rest_api.my_api.id
  stage_name  = "production"
}
```

以上でTerraformを使ってAWS API Gatewayで`robots.txt`を返す設定ができます。
このTerraform設定を適用するには、`terraform init`で初期化を行い、`terraform apply`でリソースをAWSにデプロイします。

ご参考までに、TerraformのAWSプロバイダーの詳細なドキュメントは[Terraform Registry](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)を確認してください。

デプロイしたら、ブラウザなどで
/robots.txtにアクセスしてみて、`robots.txt`が表示されるか確認してみてください。