1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自分用 Chrome拡張機能からGASへのfetchを用いたやり取り

Posted at

Chrome拡張機能からGoogle Apps Script (GAS)にアクセスして正常に通信できるようになった重要なポイントをまとめます。これを参考にすることで、今後同様の実装で問題を回避できるでしょう。

1. アーキテクチャの理解

Content ScriptとBackground Script (Service Worker)の役割分担

  • Content Script: ウェブページのコンテキストで実行され、直接外部APIにアクセスする際にCORS制限がある
  • Background Script: 拡張機能のコンテキストで実行され、manifest.jsonで設定した権限に基づいて外部APIにアクセス可能

正しい通信フロー

  1. Content Script → Background Script (メッセージ送信)
  2. Background Script → GAS API (fetch実行)
  3. GAS API → Background Script (レスポンス)
  4. Background Script → Content Script (結果返送)

2. GAS側の実装ポイント

適切なエンドポイント関数の実装
GET要求: doGet() 関数を実装
POST要求: doPost(e) 関数を実装(e.postData.contentsでPOSTデータを取得)
正しいレスポンス形式

return ContentService.createTextOutput(JSON.stringify(data))
  .setMimeType(ContentService.MimeType.JSON);

デプロイ時の注意点
新しいデプロイ作成: コード変更後は「新しいデプロイ」を作成
最新バージョン選択: デプロイ時に最新バージョンを選択
アクセス権限設定: 「全員(匿名含む)」に設定
URLの確認: デプロイ後の正確なURLを使用(/execで終わるURL)

3. Chrome拡張機能側の実装ポイント

manifest.jsonの設定

{
  "host_permissions": [
    "https://script.google.com/*",
    "https://script.googleusercontent.com/*"
  ],
  "background": {
    "service_worker": "service-worker.js"
  }
}

Background Script (Service Worker)の実装

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.type === 'fetchGAS') {
    fetch(message.url, {
      method: message.method || 'GET',
      headers: {
        'Content-Type': 'application/json'
      },
      body: message.data ? JSON.stringify(message.data) : undefined
    })
    .then(response => response.text())
    .then(text => {
      sendResponse({success: true, data: text});
    })
    .catch(error => {
      sendResponse({success: false, error: error.message});
    });
    return true; // 非同期レスポンスのために必須
  }
});

Content Scriptからの呼び出し

const response = await new Promise((resolve, reject) => {
  chrome.runtime.sendMessage(
    {
      type: "fetchGAS", 
      url: gasUrl,
      method: "POST",  // または "GET"
      data: dataToSend  // POSTの場合のみ
    },
    response => {
      if (chrome.runtime.lastError) {
        reject(new Error(chrome.runtime.lastError.message));
      } else if (!response.success) {
        reject(new Error(response.error));
      } else {
        resolve(response.data);
      }
    }
  );
});
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?