urlencode / base64gzip — URL・gzip エンコード関数

1. 概要

  • urlencode — URL安全な文字列にエンコード
  • base64gzip — gzip圧縮してBase64エンコード
  • 実際のユースケース

2. urlencode — URLエンコード

urlencode(string)はURLクエリパラメータとして安全な形式に文字列をエンコードします。スペースは+に、特殊文字はパーセントエンコードになります。

# terraform consoleで確認
> urlencode("hello world")
"hello+world"

> urlencode("a=1&b=2")
"a%3D1%26b%3D2"

> urlencode("https://example.com/path?q=terraform")
"https%3A%2F%2Fexample.com%2Fpath%3Fq%3Dterraform"

API GatewayのURLパラメータを安全にエンコードする

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名"
  type        = string
  default     = "dev"
}

variable "webhook_url" {
  description = "Webhookの転送先URL"
  type        = string
  default     = "https://hooks.example.com/services/xxx/yyy/zzz"
}

locals {
  # URLをパラメータとして別のURLに含める場合にエンコードが必要
  encoded_webhook_url = urlencode(var.webhook_url)

  # SNSのHTTPサブスクリプションエンドポイントの構築
  api_endpoint = "https://api.example.com/webhook?target=${local.encoded_webhook_url}&env=${urlencode(var.environment)}"
}

resource "aws_sns_topic" "alerts" {
  name = "${var.environment}-alerts"

  tags = {
    Name        = "${var.environment}-alerts"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

resource "aws_ssm_parameter" "api_endpoint" {
  name  = "/${var.environment}/api/endpoint"
  type  = "String"
  value = local.api_endpoint

  tags = {
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

3. base64gzip — gzip圧縮してBase64エンコード

base64gzip(string)は文字列をgzip圧縮してBase64エンコードした結果を返します。大きなユーザーデータスクリプトをEC2に渡す場合に有効です(EC2のuser_dataは16KBが上限)。

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

locals {
  # 大きなcloud-configスクリプト
  cloud_config = <<-EOT
    #!/bin/bash
    set -e
    dnf update -y
    dnf install -y nginx
    dnf install -y amazon-cloudwatch-agent
    dnf install -y aws-cli

    # Nginx設定
    cat > /etc/nginx/conf.d/app.conf << 'NGINX'
    server {
      listen 80;
      server_name _;
      location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
      }
    }
    NGINX

    systemctl enable nginx
    systemctl start nginx
  EOT
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  # gzip圧縮でuser_dataサイズを削減(16KB上限に対応)
  user_data_base64 = base64gzip(local.cloud_config)

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

user_data(Base64エンコードのみ)ではなくuser_data_base64(Base64文字列をそのまま渡す)を使うことでgzip圧縮データを直接設定できます。


4. その他のエンコード関数

# base64encode / base64decode は hash-encode記事を参照
# textencodebase64 - 指定した文字エンコードでBase64エンコード
> textencodebase64("hello", "UTF-8")
"aGVsbG8="

# textdecodebase64 - Base64をデコードして指定した文字エンコードで返す
> textdecodebase64("aGVsbG8=", "UTF-8")
"hello"

5. 関連記事


6. まとめ

  • urlencode(str) — URLクエリパラメータとして安全な形式にエンコード。スペースは+に変換
  • base64gzip(str) — gzip圧縮してBase64エンコード。大きなuser_dataスクリプトの圧縮に使う
  • gzip圧縮したuser_dataはuser_data_base64属性で渡す(user_dataではなく)
  • textencodebase64 / textdecodebase64で文字エンコード指定のBase64変換もできる

動作確認バージョン: Terraform >= 1.9 公式ドキュメント: https://developer.hashicorp.com/terraform/language/functions/urlencode