結論
GETリクエストするときは、リクエストボディではなくクエリストリングかパスパラメータを使いましょう。(掲題どおり)
ハマったこと
クライアント側はこのように呼び出し(ちなみにReactでAmplifyを使っています)
apiCall.tsx
import { API } from "aws-amplify";
export const hoge = async (
hogeId: string
): Promise<void> => {
const apiName = "hogeAPI";
const path = "/";
const params = {
body: {
hogeId: hogeId,
},
};
return await API.get(apiName, path, params);
};
APIはLambdaを使います。Lambda側ではこのように受け取り
lambda.js
exports.handler = async (event) => {
const parameter = JSON.parse(event.body);
const hogeId = parameter.hogeId
// あとは割愛
}
ただこれでAPI呼び出すと502。CloudWatchログを見てみると、bodyがnull。
GETで呼び出しするのにbody指定なのが良くない。
正しくはこう。
apiCall.tsx
import { API } from "aws-amplify";
export const hoge = async (
hogeId: string
): Promise<void> => {
const apiName = "hogeAPI";
const path = "/?hogeId=" + hogeId;
const params = {};
return await API.get(apiName, path, params);
};
Lambda側は下記。
このとき渡ってくるqueryStringParameters
の中身を見ると、一見JSON文字列のように見えて、値の部分がダブルクオートで囲まれていないため、このままJSON.parse
するとエラーになってしまう。
一度JSON.stringify
するといい。
lambda.js
exports.handler = async (event) => {
const parameter = JSON.parse(JSON.stringify(event.queryStringParameters));
const hogeId = parameter.hogeId
// あとは割愛
}
これで呼び出し成功。
GETでリクエストボディ指定しちゃダメなのは基本ですが、よく忘れてハマってしまうため備忘録メモ。
蛇足だがReactでAPIコールするときはこんな感じで呼び出せばいい。
client.tsx
import hoge from "path/to/apiCall";
hoge("hogeId")
.then((res) => {
console.log("success");
})
.catch((e) => {
console.error(e);
});
もっといい書き方がある気がしているので、あくまで参考程度でお願いします。