⚙️

GASでAuth付きGraphQLのAPIを叩く (おまけ: Firebase Auth)

2022/01/21に公開

概要

GASでGQL APIを叩きたい時はありませんか?僕はあります

  • 認証したい
  • 認証1回で複数クエリを叩きたい
  • 膨大な量叩くから6分制限が怖い
  • (firebase authを叩きたい)

をやります

実装

今回は認証がBearer Tokenだと仮定します

単発クエリ

UrlFetchApp.fetch するだけ
本体は payload に入れます

queryGQL.gs
const ENDPOINT_URL = 'https://your-gql-endpoint/'

function queryGQL(graphql) {
  const idToken = getIdToken() // お好きにどうぞ
  const options = {
    'method' : 'post',
    'contentType' : 'application/json',
    'headers' : {
      "Authorization": "Bearer " + idToken
    },
    'payload' : JSON.stringify({ query : graphql })
  };

  const response = UrlFetchApp.fetch(ENDPOINT_URL, options);
  const json = (JSON.parse(response.getContentText()));
  return json;
}

複数クエリ

UrlFetchApp.fetchAll します
GASは時間制限があるので、できるだけまとめて並列処理しましょう

queryGQL.gs
function queryAllGQL(graphqls) {
  const idToken = getIdToken() // お好きにどうぞ
  const requests = graphqls.map(graphql => {
    return {
      'url': ENDPOINT_URL,
      'method' : 'post',
      'contentType' : 'application/json',
      'headers' : {
        "Authorization": "Bearer " + idToken
      },
      'payload' : JSON.stringify({ query : graphql })
    }
  });

  // 並列処理
  const response = UrlFetchApp.fetchAll(requests);
  const json = response.map(r => (JSON.parse(r.getContentText())))
  return json;
}

使い方

queryGQLstringqueryAllGQLstring[] で渡してあげてください
mutation の場合は mutation 句を忘れずに

main.gs
function main() {
  const query1 ='{\
    user(id:"user-1"){\
      id\
      name\
    }\
  }'

  const query2 ='mutation {\
    editUser(id:"user-2", name: "Bob"){\
      id\
      name\
    }\
  }'
  
  const res1 = queryGQL(query1)
  const res2 = queryAllGQL([query1,query2])
}

ちなみに(正常に返ってきた場合の)データは .data に入っています

おまけ(Firebase Auth)

Firebase Authでemail&pass認証の場合

今回は以下のREST APIを使います
Firebase Auth と言いつつ、ちゃっかりGCPの Identity Platformです
https://cloud.google.com/identity-platform/docs/use-rest-api#section-sign-in-email-password

queryGQL.gs
// https://cloud.google.com/identity-platform/docs/use-rest-api#section-sign-in-email-password
const WEB_API_KEY = "your-firebase-project-web-api-key"
const EMAIL = "your@email.com"
const PASSWORD = "your-password"
const FIREBASE_AUTH_URL = 'https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=' + WEB_API_KEY;

// RESTでsignInWithPassword
const getIdToken = () => {
  const loginOptions = {
    'method' : 'post',
    'contentType' : 'application/json',
    'payload': JSON.stringify({
      "email": EMAIL,
      "password": PASSWORD,
      "returnSecureToken": true
    })
  }

  // login request
  const loginRes = UrlFetchApp.fetch(FIREBASE_AUTH_URL, loginOptions);

  // responseをparse
  const loginResJson = JSON.parse(loginRes.getContentText());
  return loginResJson.idToken
}

Discussion