Google Apps Scriptで転送システムが作れない件~理由とあわせて~

Google系

Google Apps Scriptで転送システムや画像バイナリ表示を作りたかったが…そもそも無理だった

自分

時間をかけて作ったのにムダ作業だったの…
透明

悔しいからブログ記事化してやる!

てことで、書きました。

できごと

自分のサーバがバレないURL転送が欲しくなった

noteに複数記事書いてると、最後に定型文とか書くよね?
そこに期間限定のメッセージとか載せたりするじゃない?
で思ったのだ。

自分

URLとバナー、書き換えれたらいいのに…

と…

URL登録しておいて、画像を書き換えたらいいかも…とは思ったし、
PHPで作ろうと思えばカンタンだけど、
複数アカウント運営なので、PHPのURLや画像URLからサーバばれて、本垢バレるじゃん。
ウマくない。

じゃあ、例えばbit.lyとかの短縮サービスを使えば、元のURLは分からないし、使えば良いかなって思うじゃん?
でも後からURL変えられない。
これで画像は解決してないし。

自分

じゃあ、GASでつくっちゃえば良くなーい?

という判断になった。

何がしたかったかまとめ(要件)

  1. 表形式でURLを管理したい ⇨ スプシ感覚でID・URL・画像などを一元管理
  2. スクリプトで処理分岐したい ⇨ ?id=xxx&type=urlのようにURL間違えにくく
  3. 公開URLがある ⇨ 外部からアクセス・表示・転送
  4. 無料で使える ⇨ コストゼロは必須
  5. 別々のURLで管理 ⇨ コピーで複数作れる

Google Apps Scriptで転送・画像読込システムを作ってみよう!

データ管理

スプレッドシートに以下のように登録

id url image
koudou https://note.com/kuraeqooga https://qooga.jb-jk.net/item/image/cover/qooga/2025/koudou-switch.png
…以下略… …以下略… …以下略…

idの値を『探索キー』として、データベースのように使う。

API

https://script.google.com/macros/s/なんとかかんとか/exec?id=【探索キー】&type=【urlかimage】

APIアクセス方法

…?id=【探索キー】&type=url ⇨ 302リダイレクト
…?id=【探索キー】&type=image ⇨ 画像バイナリ表示

Apps Scriptコード

function doGet(e) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
  const idParam = e.parameter.id;
  const typeParam = e.parameter.type;

  const idColumn = sheet.getRange(1, 1, sheet.getLastRow()).getValues().flat();
  const rowIndex = idColumn.indexOf(idParam);

  if (rowIndex === -1) {
    return ContentService.createTextOutput("ID not found").setMimeType(ContentService.MimeType.TEXT);
  }

  const row = sheet.getRange(rowIndex + 1, 1, 1, 3).getValues()[0];

  if (typeParam === "url") {
    const redirectUrl = row[1];

    if (!redirectUrl || redirectUrl.trim() === "") {
      return ContentService.createTextOutput("Invalid URL").setMimeType(ContentService.MimeType.TEXT);
    }

    return HtmlService.createHtmlOutput(`<script>location.href='${redirectUrl}'</script>`);
  }

  if (typeParam === "image") {
    const imageUrl = row[2];
    const response = UrlFetchApp.fetch(imageUrl);
    const blob = response.getBlob();
    blob.setName("image.png"); // 任意のファイル名

    return blob;
  }

  return ContentService.createTextOutput("Invalid type").setMimeType(ContentService.MimeType.TEXT);
}

appsscript.json対応

設定されてないと、以下のメッセージが出る。

exception: urlfetchapp.fetch を呼び出す権限がありません。

『プロジェクトの設定』⇨『「appsscript.json」マニフェスト ファイルをエディタで表示する』をチェック
エディタに出来た『appsscript.json』に

  "oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/spreadsheets"
  ]

を追加しておく。

デプロイして許可を忘れずに

「テストだけでいいやー」て場合でも、1回デプロイして許可しないと使えないから注意。
やりかたは割愛する。

結果

302リダイレクト

redirect
あ・・・

画像バイナリ表示

画像バイナリ
あ・・・

自分

そうだね!
GASで作るとそうになっちゃうよね!

Google Apps Scriptには制約がある

GASには色々制約があるから、作れないものもあるのだ。
もう目に馴染んでて忘れてたけど、iFrameもその1つ。

GAS Webアプリの制約ポイント

おおよそこんな感じ

制約 詳細
iframe表示 GASのWebアプリはGoogleドメイン内でiframeタグに包まれる
window.location.hrefでのリダイレクト iframeタグ内なので親ページには効かない。iFrame禁止になってるサイトなら読込禁止になる
X-Frame-Optionsの制御 HtmlService.setXFrameOptionsMode()で一部制御可能ではあるが…制限あり
外部埋め込み不可 GASのWebアプリは他ドメインからの埋め込みを基本的に拒否する

他にも画像読み込むのにクロスドメインだとか、GASで読込禁止だーだとかまぁつまり

結論:転送も画像バイナリ表示もGASでは無理

作ろうと思った方の参考になればいいね!

いぬ

えー?
もう『要件』を叶える方法はないの?

て言われると、そんなことはなくて、代わりになるものは存在する。

GASの代替になるスクリプト環境+公開URL対応サービス

調べるのめんどくさいからCopilotさんにお願いした。
間違ってたらごめんね。

サービス 特徴 公開URL 画像/リダイレクト対応 備考
Firebase Hosting + Cloud Functions JS/TSで自由にAPIとページ構築 独自URL可 完全制御可能 Google製。GASより自由度高い
Vercel / Netlify HTML/JSをGit連携で即公開 独自ドメイン対応 iframe制限なし 静的サイト+APIもOK
Glitch ブラウザでNode.js開発可 即時公開 Expressで自由制御 学習にも向いてる。無料枠あり
Replit Python/Nodeなど多言語対応 Web公開可 Webサーバ構築可能 GASより柔軟。教育向けにも人気
Cloudflare Pages + Workers 高速CDN+JSベースAPI 高速公開 リダイレクト・画像制御OK 軽量で爆速。無料枠も強い
管理方法 表形式 スクリプト制御 公開URL 無料枠 テンプレート化
GAS(制限あり) ⚠️ iframe制限
Notion + Vercel(またはReplit)
Airtable + Workers
Firebase + スプレッドシート ✅(やや重)
自分

自分は複数URL欲しいから『Notion + Vercel』にしようかと!
けど…いつやろうかな…

Vercelの公開URLについて

  1. デフォルトURL ⇨ https://your-project-name.vercel.app(無料で発行)
  2. 複製時のURL ⇨ プロジェクト名が違えば `your-copy.vercel.app` など別URLになる
  3. サブドメイン運用 ⇨ client1.vercel.appclient2.vercel.appのように分けられる
  4. 独自ドメイン ⇨ 任意。使いたければ設定可能(無料枠でもOK)

コメント

タイトルとURLをコピーしました