Google Apps ScriptでWebアプリのURLを取得する【GAS】

以前は簡単に取得できたデプロイしたウェブアプリのURLの取得なのですが、現在V8がオンの状態では依然として誤ったURLが返ってくる状態で、正しいURLが取得出来ない状況にあります。この問題に対してStackOverFlowではGCPのApps Script APIのDeployments.listを利用して取得する方法を提示しています。現在、Apps Script APIは旧Execution APIの機能である「直接REST APIのようにGASの関数を叩く」という機能の他にこういった機能も持ち合わせています。

今回はこのApps Script APIを利用して正しいデプロイされたURLを取得する方法を調べてみました。

今回利用するスプレッドシート

上記のサンプルをデプロイして、ウェブアプリとして見られるようにしてから、関数を実行します。今回はApps Script APIを利用するので、GCP側での設定やGAS側での準備が必要です。

※但し今回の手法はドメインおよびGCPが必要なのでGoogle Workspace専用になります。

Google Apps Scriptを色々なアプリから実行する【GAS】

事前準備

GCP側の準備

GASのプロジェクトを紐付けする

外部のメンバー参加の場合には、Google Apps ScriptとCloud Consoleのプロジェクトを紐付けする作業が必要です。以下の手順でプロジェクトの変更を行います。前述のプロジェクトの控えておいた番号を利用します。そうでない場合はプロジェクト移動をせずとも利用が出来ました(内部メンバーのみの場合)。

  1. Cloud Console側のプロジェクトのホームを開き、「プロジェクト番号」を控えておく
  2. Google Apps Scriptのスクリプトエディタを開く
  3. サイドバーからプロジェクト設定を開く
  4. GCPプロジェクトの「プロジェクトを変更」をクリック
  5. GCPのプロジェクト番号に、1.の番号を入力して、プロジェクトを設定をクリック
  6. これで紐付けが完了しました。

図:プロジェクトの移動も必須の作業です

APIを有効にする

Google Cloud Console側でもAPIを有効化する必要性があります。

  1. GCPのプロジェクトを開く
  2. 左サイドバーからAPIとサービスにて、「APIとサービスの有効化」をクリックする
  3. Apps Scriptと検索すると出てくるので、クリックします。
  4. 有効化をクリックします。
  5. 認証情報の作成は不要です

図:有効化をしておくだけでOK

GAS側の準備

appsscript.jsonに記述を追加する

スクリプトエディタの左サイドバーから「プロジェクト設定」を開き、「appsscript.json」マニフェスト ファイルをエディタで表示するにチェックを入れて、appsscript.jsonを表示する。その後そのファイルを開き、以下のように記述を行います。必須の作業です。これをしてしまうと、今後メソッドを追加したときに追加の認証は手動で、Scopeを入れてあげないと認証されないので要注意。

{
        ...
       "oauthScopes": [
              "https://www.googleapis.com/auth/script.deployments",
              "https://www.googleapis.com/auth/spreadsheets",
              "https://www.googleapis.com/auth/userinfo.profile",
              "https://www.googleapis.com/auth/script.external_request"
       ],
       ...
}

https://www.googleapis.com/auth/script.deployments」が上記のように指定する必要があります。これを指定しておかないと403エラー Permission Denied等のエラーが発生してしまいます。

初回認証をしておく

ここまでの準備で適当な関数を用意して実行すると認証が始まります。「Google Apps Script のデプロイの作成と更新」というスコープが出てくるはずです。

図:認証を実行するとこの画面が出る

コードと出力結果

ソースコード

//ドメイン
var domain = "ここにドメインを入れる";

//外部貼り付け用
function doGet(e){
  var html = HtmlService.createTemplateFromFile("index").evaluate()
  html = html.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
  return html;
}

//ウェブアプリのURLを生成して返す
function depidview(){
  //デプロイIDを取得する
  var deplist = getDeploymentID();
  var devid = deplist[0].deploymentId;   //devの場合のデプロイメントIDを取得

  //URLを構成して返す
  var url = `https://script.google.com/a/macros/${domain}/s/${devid}/dev`;
  console.log(url)
  
}

//デプロイIDを取得する
function getDeploymentID(){
    //デプロイ情報をまとめる
    const option = {
      version: 1,
      id: ScriptApp.getScriptId(),
      token: ScriptApp.getOAuthToken(),
      page: "",
      size: 50,
      type: "WEB_APP",
    }

    const uri = `https://script.googleapis.com/v${option.version}/projects/${option.id}/deployments`;

    const fullURI = `${uri}?pageSize=${option.size}${option.page ? `&pageToken=${option.page}` : ""}`;

    const params = {
      contentType: "application/json",
      headers: {
        Authorization: `Bearer ${option.token}`,
      },
      muteHttpExceptions: true,
      method: "get",
    };

    const deps = [];

    const response = UrlFetchApp.fetch(fullURI, params);

    if (response.getResponseCode() !== 200) {
      console.log(response.getContentText());
      return deps;
    }

    const { deployments, nextPageToken } = JSON.parse(response.getContentText());

    const requested = deployments.filter(({ entryPoints }) =>
      entryPoints.some(({ entryPointType }) => entryPointType === option.type)
    );

    deps.push(...requested);

    if (nextPageToken) {
      deps.push(...getDeployments(option));
    }

    return deps;
}
  • depidview関数を実行すると、deploymentIdを取得して、それを元にアクセスできるURLを構築します。
  • getDeploymentIDは、Apps Script APIにアクセスして、デプロイIDをまとめて取得してきます。

これで、2パターンのデプロイメントIDが取得できるので、GAS上でのデプロイしたウェブアプリのURLを取得することが可能です。

出力結果

[ 
  { deploymentId: 'AKfycbx0oVX3jIEfzVN8S6O7xxxxxxxxxxxx,
    deploymentConfig: 
     { scriptId: '1N8QVTfKQz9slwFGQo_EjnuSUFh3lpHnHNspUxOHvxxxxxxxxx',
       manifestFileName: 'appsscript' },
    updateTime: '1970-01-01T00:00:00Z',
    entryPoints: [ [Object] ] },
  { deploymentId: 'AKfycbwstmmvP13AUhhtLwOjrWwMEV3UsGQ0X0hWAk0B4WtjgEtVGWZFxxxxxxx',
    deploymentConfig: 
     { scriptId: '1N8QVTfKQz9slwFGQo_EjnuSUFh3lpHnHNspxxxxxxx',
       versionNumber: 1,
       manifestFileName: 'appsscript' },
    updateTime: '2023-04-27T04:24:17.885Z',
    entryPoints: [ [Object] ] } 
]

上記では2つ出力されてるのですが、これなのですが

  • 1つ目のdeploymentIdは、devで終わるURLの場合はこちらを使用
  • 2つ目のdeploymentIdは、execで終わるURLの場合はこちらを使用

ということになっています。また、そもそも旧式の「ScriptApp.getService().getUrl()」なのですが、これURLの中でドメインが入る場所が間違ってる為、アクセス出来なくなっているので、URLは以下のように組み立てて返して上げれば良いです。

https://script.google.com/a/macros/ドメイン/s/デプロイメントID/dev

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)