michimani.net

ALB のパスベースルーティングとクエリパラメータの関係

2021-08-23

Application Load Balancer のパスベースルーティングにて、パスをワイルドカード指定しなかった場合のクエリパラメータがどのような扱いになるのかを確かめてみました。

目次

結論

The path pattern is applied only to the path of the URL, not to its query parameters. It is applied only to visible ASCII characters; control characters (0x00 to 0x1f and 0x7f) are excluded.

Listeners for your Application Load Balancers - Elastic Load Balancing

ざっくり日本語訳。

パスパターンは、URLのパスにのみ適用され、クエリパラメーターには適用されません。また、制御文字(0x00~0x1f、0x7f)を除く、可視のASCII文字にのみ適用されます。

やったこと

手順

Application Load Balancer 作成

SUBNET_ID_1="subnet-0561f45xxxxxxxxxx" SUBNET_ID_2="subnet-036c672xxxxxxxxxx" \
ALB_ARN=$(
  aws elbv2 create-load-balancer \
  --name path-routeing-lb \
  --subnets "${SUBNET_ID_1}" "${SUBNET_ID_2}" \
  --region ap-northeast-1 \
  --query "LoadBalancers[0].LoadBalancerArn" \
  --output text
) \
&& echo "${ALB_ARN}" 

出力

arn:aws:elasticloadbalancing:ap-northeast-1:000000000000:loadbalancer/app/path-routeing-lb/aac5a9xxxxxxxxxx

リスナーを追加

LISTENER_ARN=$(
  aws elbv2 create-listener \
  --load-balancer-arn "${ALB_ARN}" \
  --protocol HTTP \
  --port 80 \
  --default-actions '{"Type":"fixed-response","FixedResponseConfig":{"MessageBody": "{\"message\":\"This is the default action.\"}","StatusCode":"200","ContentType":"application/json"}}' \
  --query "Listeners[0].ListenerArn" \
  --output text
) \
&& echo "${LISTENER_ARN}"

出力

arn:aws:elasticloadbalancing:ap-northeast-1:000000000000:listener/app/path-routeing-lb/aac5a9xxxxxxxxxx/8fea4fxxxxxxxxxx

追加したリスナーが正しく動作するか確認します。

まずは作成した ALB の DNS 名を取得しておきます。

DNS_NAME=$(
  aws elbv2 describe-load-balancers \
  --load-balancer-arns "${ALB_ARN}" \
  --query "LoadBalancers[0].DNSName" \
  --output text
)

この時点ではセキュリティグループのインバウンド設定によってアクセスできないので、自分のマシンの IP からのみ 80 ポートにアクセスできるようにします。

まず セキュリティグループ ID を取得します。

SG_ID=$(
  aws elbv2 describe-load-balancers \
  --load-balancer-arns "${ALB_ARN}" \
  --query "LoadBalancers[0].SecurityGroups[0]" \
  --output text
)

続いて、自分のマシンの IP を取得します。

MY_IP=$(curl http://checkip.amazonaws.com/)

それらの値を使用してインバウンドルールを作成します。

aws ec2 authorize-security-group-ingress \
--group-id "${SG_ID}" \
--protocol tcp \
--port 80 \
--cidr "${MY_IP}"/32

これで ALB に対して DNS 名でアクセスできるようになったので、 httpie1 でリクエストを送信してみます。

$ http "${DNS_NAME}"

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 41
Content-Type: application/json; charset=utf-8
Date: Mon, 23 Aug 2021 14:06:56 GMT
Server: awselb/2.0

{
    "message": "This is the default action."
}

設定した固定値のレスポンスが返ってきました。

パスベースのルーティングを追加

続いて、パスベースのルーティングを追加します。

今回は、下記のようなルーティングを追加してみます。

aws elbv2 create-rule --listener-arn "${LISTENER_ARN}" --priority 1 \
--conditions Field=path-pattern,Values='/not-found' \
--actions '{"Type":"fixed-response","FixedResponseConfig":{"MessageBody": "{\"message\":\"This is 404 path.\"}","StatusCode":"404","ContentType":"application/json"}}' \
&& aws elbv2 create-rule --listener-arn "${LISTENER_ARN}" --priority 2 \
--conditions Field=path-pattern,Values='/error' \
--actions '{"Type":"fixed-response","FixedResponseConfig":{"MessageBody": "{\"message\":\"This is 500 path.\"}","StatusCode":"500","ContentType":"application/json"}}'

それぞれのパスにアクセスしてみます。

$ http "${DNS_NAME}/not-found"

HTTP/1.1 404 Not Found
Connection: keep-alive
Content-Length: 31
Content-Type: application/json; charset=utf-8
Date: Mon, 23 Aug 2021 14:15:16 GMT
Server: awselb/2.0

{
    "message": "This is 404 path."
}
$ http "${DNS_NAME}/error"

HTTP/1.1 500 Internal Server Error
Connection: keep-alive
Content-Length: 31
Content-Type: application/json; charset=utf-8
Date: Mon, 23 Aug 2021 14:15:32 GMT
Server: awselb/2.0

{
    "message": "This is 500 path."
}

ワイルドカードで指定していないので、上記から始まるパスであってもそれらに続くパスへのリクエストに対しては、ルールにマッチせずにデフォルトのレスポンスが返ります。

$ http "${DNS_NAME}/error-error"

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 41
Content-Type: application/json; charset=utf-8
Date: Mon, 23 Aug 2021 14:16:58 GMT
Server: awselb/2.0

{
    "message": "This is the default action."
}

クエリパラメータを付与してリクエスト

では、クエリパラメータが付与されている場合はどうなるでしょうか。

/error?errorType=internal-server-error というクエリパラメータを付与してリクエストしてみます。

$ http "${DNS_NAME}/error?errorType=internal-server-error"

HTTP/1.1 500 Internal Server Error
Connection: keep-alive
Content-Length: 31
Content-Type: application/json; charset=utf-8
Date: Mon, 23 Aug 2021 14:19:04 GMT
Server: awselb/2.0

{
    "message": "This is 500 path."
}

500 のレスポンスが返ります。
つまり、パスベースのルーティングでは 指定したパスにクエリパラメータの部分は含まれまれず、ルールの判定にはクエリパラメータを除くパス部分のみで判定されます。逆に言うと、特定のパスに対してクエリパラメータを考慮したパスルーティングをしたい場合であっても、ワイルドカードで /error* のように指定する必要はありません。

掃除

セキュリティグループのインバウンドルールを削除

aws ec2 revoke-security-group-ingress \
--group-id "${SG_ID}" \
--protocol tcp \
--port 80 \
--cidr "${MY_IP}"/32

ALB を削除

aws elbv2 delete-load-balancer \
--load-balancer-arn "${ALB_ARN}"

  1. CLI で http リクエストするなら HTTPie が便利 - michimani.net  ↩︎


comments powered by Disqus