LoginSignup
5
1

GCPのAPI GatewayでCORSを有効にする方法を解説するよ

Last updated at Posted at 2022-05-20

経緯(時系列順)

  1. GCPのAPI Gatewayでお手軽簡単にPublic APIを立てようとしたら、CORS(オリジン間リソース共有) が無効になっていて、ブラウザ上のJavaScriptからFetchできなかった

  2. 悲しい

  3. 何かCORSを有効化する方法あるはずだから調べてやってみよう

結論

下記を全部やれば、できるようになるよ!

  1. Google Cloud API GatewayのAPI定義(OpenAPI仕様)で、CORSサポートを有効にする

  2. 同上のAPI定義で、CORSの Preflight request のパスを定義する

  3. APIバックエンド(Cloud Functionsとか)で、CORS Preflight request時と通常のリクエスト時の双方について、CORS周りのヘッダを追加する

とりあえずコード見せて欲しい

Hello WorldするだけのWeb-APIを例に、CORS対応前後を比較するよ。

なお構成はこんな感じだよ

  • APIバックエンド(今回は Cloud Functions で実装する)
    • Cloud FunctionsのURL: 仮に「https://asia-northeast1-hogehoge.cloudfunctions.net/hello」とする
  • API Gateway
    • URL「/greet」 で上記のCloud Functionsをコールする

Google Cloud API GatewayのAPI定義(OpenAPI仕様)

CORS対応前

swagger: '2.0'
info:
  title: api-gateway-on-hogehoge
  description: Sample API on API Gateway with a Google Cloud Functions backend
  version: 1.0.0
schemes:
  - https
produces:
  - application/json
paths:
  /greet:
    get:
      summary: Greet a user
      operationId: hello
      x-google-backend:
        address: https://asia-northeast1-hogehoge.cloudfunctions.net/hello
      responses:
        '200':
          description: A successful response
          schema:
            type: string

CORS対応後

# https://cloud.google.com/api-gateway/docs/secure-traffic-console?hl=ja
swagger: '2.0'
info:
  title: api-gateway-on-hogehoge
  description: Sample API on API Gateway with a Google Cloud Functions backend
  version: 1.0.0
schemes:
  - https
produces:
  - application/json
x-google-endpoints:
  - name: endpoints-for-hogehoge-api
    allowCors: True
paths:
  /greet:
    options:
      summary: cors
      operationId: corsHello
      x-google-backend:
        address: https://asia-northeast1-hogehoge.cloudfunctions.net/hello
      responses:
        '200':
          description: A successful response
          schema:
            type: string
    get:
      summary: Greet a user
      operationId: hello
      x-google-backend:
        address: https://asia-northeast1-hogehoge.cloudfunctions.net/hello
      responses:
        '200':
          description: A successful response
          schema:
            type: string

APIバックエンド(今回は Cloud Functions で実装)

CORS対応前

exports.helloWorld = (req, res) => {
  const message = req.query.message || req.body.message || 'Hello World!';
  res.status(200).send(message);
};

CORS対応後

exports.helloWorld = (req, res) => {
  // ---- CORS有効化 ----
  res.setHeader("Access-Control-Allow-Origin", "*");
  if (req.method === "OPTIONS") {
    // ---- CORS Preflight requestに応える ----
    res.setHeader("Access-Control-Allow-Methods", "POST, GET");
    res.setHeader("Access-Control-Allow-Headers", "Content-Type");
    res.setHeader("Access-Control-Max-Age", "3600");
    res.status(204).send("");
    return;
  }
  const message = req.query.message || req.body.message || 'Hello World!';
  res.status(200).send(message);
};

実際にブラウザからコールしてみる

Webページのどこかにたとえばこんな感じでコールできる処理書いてみると...

<!-- URLは API Gatewayのものを指定 -->
<div onclick="fetch('https://api-gateway-on-hogehoge-aqiduyfc.an.gateway.dev/greet').then(res=>res.ok ? res.text().then(console.log) : console.log('error occured'))">hogehoge</div>

無事応答が返ってきた!

Hello World!

まとめ

  • before: Google Cloud API Gateway をブラウザから叩けなくて悲しい(悲しみのあまり仕事が捗らなくなる)
  • after: OpenAPI仕様とAPIバックエンドいじってCORS有効化できたことで、Webページ上からドメイン(正確にはオリジン)違っててもAPI叩けるようになって嬉しい(テンションが上がって仕事が捗るようになる)

著者プロフィール

faable01です。かつては創作仲間と小説を書いたり、製菓業界で楽しくやっていたはずが、紆余曲折を経て、サーバーレス技術を触るのが好きなITエンジニアになっていました。AWSのIaC兼サーバレス爆速開発ツール 「SST」 が好きです。個人ブログでもたまに記事を書いています。

それから、業務日報SaaS 「RevisNote」 を運営しています。リッチテキストでの日報と、短文SNS感のある分報を書けるのが特徴で、組織に所属する人数での従量課金制です。アカウント開設後すぐ使えて、無料プランもあるから、気軽にお試しください。

5
1
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
5
1