こんにちは!システム開発チームです。
2025年11月、CloudFront Functions の Javascript ランタイム (cloudfront-js-2.0) に rawQueryString() というヘルパーメソッドが追加されました。
このメソッドを利用してクエリ文字列を取得するリダイレクト処理を実装していた際、期待した値が取得できない場面がありました。
最初は実装方法やテストイベントの指定を疑いましたが、調べていくとコンソールテスト上の挙動と、実際のリクエストでの挙動に違いがあることが分かりました。
この記事では、rawQueryString() の挙動でハマった内容と、実際に動かして確認した結果についてまとめます。
今回やりたかったことは、リクエスト URL に含まれるクエリ文字列をそのまま取得することです。
たとえば、以下のような URL にアクセスされたとします。
https://www.example.com/sample/page/?a=1&b=2
このとき、CloudFront Function 側で a=1&b=2 を取得したい、という内容です。
CloudFront Functions には rawQueryString() というメソッドがあり、リクエスト URL に含まれるクエリ文字列を、先頭の ? を除いた形で取得できます。
実装としては、以下のようなイメージです。
function handler(event) {
var request = event.request;
var raw = request.rawQueryString();
console.log('rawQueryString=' + String(raw));
return request;
}
期待するログは以下ですが、ここで問題がありました。
rawQueryString=a=1&b=2
CloudFront Functions のコンソールテストで、以下のようなイベント JSON を指定しました。
{
"version": "1.0",
"context": {
"eventType": "viewer-request"
},
"viewer": {
"ip": "1.2.3.4"
},
"request": {
"method": "GET",
"uri": "/sample/page/",
"headers": {},
"cookies": {},
"querystring": {
"a": { "value": "1" },
"b": { "value": "2" }
}
}
}
querystring に a=1 と b=2 相当の値を指定しているため、最初は rawQueryString() でも a=1&b=2 が取得できると思っていました。
しかし、実際に確認すると rawQueryString() は期待通りの値になりませんでした。
rawQueryString=
この時点では、rawQueryString() の使い方を間違えているのか、テストイベントの指定方法が違うのか、少し判断しづらい状態でした。
切り分けのために、同じテストイベントで request.querystring も確認してみました。
function handler(event) {
var request = event.request;
console.log('querystring=' + JSON.stringify(request.querystring));
console.log('rawQueryString=' + String(request.rawQueryString()));
return request;
}
すると、request.querystring には値が入っていました。
querystring={"b":{"value":"2"},"a":{"value":"1"}}
rawQueryString=
つまり、クエリ文字列の情報がまったく渡っていないわけではありません。
request.querystring では取れているのに、rawQueryString() では取れていない。
ここで、この2つの違いを整理する必要がありました。
request.querystring は、CloudFront Functions のイベントオブジェクトに含まれる、パース済みのクエリ情報です。
今回の例でいうと、以下のような形です。
{
a: { value: "1" },
b: { value: "2" }
}
一方で、rawQueryString() が返すのは、リクエスト URL に含まれていた生のクエリ文字列です。
a=1&b=2
つまり、両方ともクエリ文字列に関する情報ですが、扱っている形式が違います。
request.querystring
→ パース済みのクエリオブジェクト
request.rawQueryString()
→ URL に含まれていた生のクエリ文字列
ここで重要なのは、rawQueryString() は request.querystring を見て文字列を組み立て直すメソッドではない、という点です。
そのため、テストイベントの querystring に値を入れても、それだけで rawQueryString() が a=1&b=2 を返すわけではありませんでした。
コンソールテスト上では rawQueryString() の値をうまく確認できませんでしたが、実際に CloudFront Function を紐づけた状態でクエリ文字列付きの URL にアクセスすると、期待通りに取得できました。
たとえば、以下のような URL でアクセスします。
https://www.example.com/sample/page/?a=1&b=2
この場合、rawQueryString() のログは以下のようになりました。
rawQueryString=a=1&b=2
つまり、rawQueryString() 自体が使えないわけではなく、コンソールテストのイベント JSON に querystring を指定しただけでは、生のクエリ文字列としては扱われない、という理解です。
コンソールテストはイベントオブジェクトを使って関数の動作を確認できる便利な機能ですが、実際の HTTP リクエストを完全に再現しているわけではありません。
そのため、rawQueryString() のように実リクエスト由来の情報を扱う場合は、最終的に実際のリクエストで確認するのが確実でした。
今回のハマりポイントは、以下の思い込みでした。
request.querystring に値がある
= rawQueryString() でも同じ値が取れる
実際には、これは成り立ちません。
request.querystring は、パース済みのクエリオブジェクトです。
一方、rawQueryString() は、リクエスト URL に含まれていた生のクエリ文字列を返すメソッドです。
そのため、request.querystring に値が入っていても、rawQueryString() が同じ内容を文字列として返すとは限りません。
今回の確認では、コンソールテスト上では rawQueryString() の値を期待通りに確認できませんでしたが、実際のクエリ文字列付きリクエストでは取得できました。
CloudFront Functions で rawQueryString() を使う場合は、request.querystring との違いに加えて、コンソールテストと実際のリクエストで確認できる内容が異なる点も意識しておくとよさそうです。