GASのリクエストとレスポンスについてわかりやすくまとめてみた
はじめに
GASのウェブアプリケーションAPIにPOSTリクエストを送る際にCORSエラーが出てしまったので、この機会に解決方法とGASのリクエストとレスポンスについて自分なりにわかりやすくまとめてみました。
CORSエラーとは
GASではスクリプトのエラーがあった場合にもCORSエラーが表示されます。
ですので、下記で解決しない場合はスクリプトの内容も確認した方が良いかと思います。
CORSエラーを回避する方法
①リクエストヘッダを設定しない
下記の場合にはJSONデータを送信しているので、Content-Type: application/json
を明示的に設定するのが適切です。
しかし、GASにリクエストを送る場合はContent-Typeがapplication/json
だとCORSエラーが発生してしまうので、下記のようなbodyがJSON形式の場合はリクエストヘッダを設定していません。
// https://script.google.com/macros/s/*****/exec
const endPoint = process.env.NEXT_PUBLIC_ENDPOINT || '';
fetch(endPoint, {
method: 'POST',
body: JSON.stringify({ data: data }),
})
// HTTPリクエストが完了した場合
.then((response) => {
console.log('response', response.body);
if (!response.ok) {
console.error('レスポンスが失敗しました。');
throw new Error('Network response was not ok.');
}
return response.text();
})
②単純リクエストとして送信する
HTTPリクエストのbodyに含まれるデータの種類によりますが、text/plain
または application/x-www-form-urlencoded
をContent-Typeとして指定して、追加のセキュリティチェック(プリフライトリクエスト)を行わずに直接サーバーに単純リクエストを送信してください。
const data = {
name: 'Mike',
age: 30,
};
const formData = new URLSearchParams();
formData.append('data', JSON.stringify(data));
fetch(endPoint, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
// URLエンコードされた文字列を生成する key=value&key2=value2のような形式です
body: formData.toString(),
})
// HTTPリクエストが完了した場合
.then((response) => {
console.log('response', response.body);
if (!response.ok) {
console.error('レスポンスが失敗しました。');
throw new Error('Network response was not ok.');
}
return response.text();
})
GASからのレスポンスについて
GASからのレスポンスは、成功時に302 FOUND Access-Control-Allow-Origin * 、
失敗の場合は200 OK Access-Control-Allow-Origin は設定されずに返ってきます。
no-cors
Request.modeをno-cors(mode: 'no-cors'
)にすると送られるHeaderが制限されてCORSエラーは出なくなりリクエストは送れますが、その内容は不透明(opaque)とみなされ、レスポンスの内容は読み込めません。
レスポンスの内容
type: "opaque" URL list: 空 status: 0 status message: 空文字列 header list: 空 body: null
GAS側のコード
doPost関数で受け取れるデータは、postData
プロパティを介してアクセスする必要があり、postData.contents
を使用してPOSTリクエストのボディに含まれるデータを取得します。
イベント オブジェクトの構造
const doPost = (e: GoogleAppsScript.Events.DoPost) => {
// POSTリクエストのボディからJSON文字列を取得し、パースする
const payload = JSON.parse(e.data.contents);
// dataオブジェクトにアクセス
const name = payload.name; //'Mike'
// JSON文字列に変換する
const response = JSON.stringify({
result: 'Success',
message: 'リクエストに成功しました。',
});
// JSON形式のレスポンスを返す
return ContentService.createTextOutput(response).setMimeType(
ContentService.MimeType.JSON
);
}
参考にさせていただきました
終わりに
何かありましたらお気軽にコメント等いただけると助かります。
ここまでお読みいただきありがとうございます🎉
Discussion