API Gateway→Lambdaをaxiosを使ってクライアントから実行
Lambdaを利用することで運用コストを抑えたサーバーレスWebアプリの開発が可能になります。
AWSのチュートリアルで Lambda, DynamoDB, API Gateway の連携方法があるのでそちらを参考にバックエンド(API)を作成しました。
作成した API に対して axios を使ってリクエストを送る方法やAPI Gatewayの設定について書いていきます。
APIの動作確認
今回は倉庫の登録と一覧取得を行うためのAPIを作成しています。
それぞれのリクエスト内容は以下のような感じです。(URLは適当)
-
一覧取得
GET https://asdfghzxcvb.execute-api.eu-west-1.amazonaws.com/warehouses
-
新規登録
PUT https://asdfghzxcvb.execute-api.eu-west-1.amazonaws.com/warehouses Parameter Body { "id": "200", "name": "CCC", "price": 5000 }
レスポンスは以下のような感じです。
-
一覧取得
{ "Items": [ { "price": 3000, "id": "123", "name": "AAA" }, { "price": 4000, "id": "124", "name": "BBB" } ], "Count": 2, "ScannedCount": 2 }
-
新規登録
"Put item: 200"
クライアント側の実装
今回、axiosはCDNで読み込んで使います。
作成したファイルは以下の2つです。
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>shawa</title>
<style></style>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="./index.js"></script>
</head>
<body>
<h3>倉庫の登録</h3>
<label>ID</label>
<input type="text" id="id" />
<br />
<label>名称</label>
<input type="text" id="name" />
<br />
<label>料金/日</label>
<input type="number" id="price" />
<br />
<button type="button" id="register">登録</button>
<hr />
<h3>倉庫の一覧</h3>
<form id="list"></form>
</body>
</html>
index.js
axios.defaults.baseURL =
"https://a2nqdcb2ch.execute-api.eu-west-1.amazonaws.com";
function getList() {
axios.get("/warehouses").then((res) => {
for (let item of res.data.Items) {
let div = document.createElement("div");
let label = document.createElement("label");
let radio = document.createElement("input");
radio.setAttribute("type", "radio");
radio.setAttribute("name", "select");
radio.setAttribute("value", item.price);
label.innerText = `[${item.id}] ${item.name} : ${item.price}円/日`;
div.append(radio);
div.append(label);
document.getElementById("list").append(div);
}
});
}
window.addEventListener("load", () => {
getList();
const inputId = document.getElementById("id");
const inputName = document.getElementById("name");
const inputPrice = document.getElementById("price");
const registerButton = document.getElementById("register");
const list = document.getElementById("list");
registerButton.addEventListener("click", () => {
let input = {
id: inputId.value,
name: inputName.value,
price: inputPrice.value,
};
axios
.put("/warehouses", input)
.then((res) => console.log(res))
.catch((e) => console.log(e));
});
});
画面表示はこんな感じです。
API Gatewayの設定
クライアントとAPIは別オリジンなのでそのまま通信しようとするとCORSでリクエストがブロックされてしまいます。
ブラウザのConsoleには以下のようなメッセージが表示されるはずです。
Access to XMLHttpRequest at 'https://asdfghzxcvb.execute-api.eu-west-1.amazonaws.com/warehouses' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
isAxiosError.js:12 GET https://asdfghzxcvb.execute-api.eu-west-1.amazonaws.com/warehouses net::ERR_FAILED 200
(anonymous) @ isAxiosError.js:12
e.exports @ isAxiosError.js:12
e.exports @ isAxiosError.js:12
l.request @ isAxiosError.js:12
r.forEach.l.<computed> @ isAxiosError.js:12
(anonymous) @ isAxiosError.js:12
getList @ index.js:7
(anonymous) @ index.js:25
load (async)
(anonymous) @ index.js:24
127.0.0.1/:1 Uncaught (in promise) o {message: 'Network Error', name: 'AxiosError', code: 'ERR_NETWORK', config: {…}, request: XMLHttpRequest, …}
対応策としてLambda側でレスポンスのHeaderにAccess-Control-Allow-Originなどを設定する方法もありますが、API GatewayコンソールからCORSの設定をした方が簡単です。
今回はこのように設定しました。
Access-Control-Allow-Originに * を設定するのはセキュリティ上よくないので本番稼働時には該当のオリジンを指定した方がいいです。
上記の設定に変更するとデータ取得ができるようになるはずです。
登録データがある場合は一覧に表示されます。
まとめ
クライアントサイドから axios を使って API Gateway 経由でデータ通信をする方法について解説しました。
基本的な内容でしたが似たようなWebアプリの開発をする際の参考になれば幸いです。
Lambdaを使うことでコストを抑えられる点は大きなメリットですね。インフラはAWSに任せてアプリの開発に注力できるようになるも嬉しいので積極的に使っていきたいと思います。
Discussion