0
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?

はじめてのリバースプロキシ Cloud Run CORSエラー回避

Last updated at Posted at 2025-03-07

リバースプロキシとは

Reactを扱うAIのv0にはまりBlueSkyの画像検索サイトを作っていました。
気に入ったものはボタンを押すとすぐに画像がダウンロードできるという仕様にしたのですがBlueSkyの画像のURLをfetchするとどうにもエラーがでてしまいます。

画像をダウンロードする関数(javascript)
function imagedownload(image_url) {

    fetch(image_url)
    .then(response => response.blob())
    .then(blob => {
        const url = window.URL.createObjectURL(blob)
        const a = document.createElement('a')
        a.style.display = 'none'
        a.href = url
        a.download = "image.jpg"
        document.body.appendChild(a)
        a.click()
        window.URL.revokeObjectURL(url)
    })
    .catch(() => console.error('download error'))
}
エラー内容
' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

例えば以下のURLでこの関数を使うとエラーになります。
https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:2et4xgrlwcqymiyjpvdv4yle/bafkreia7fdlsuaob47fjxy2umdnah6iuiqfy7wew6gg7ampwptwch6ughu@jpeg


React初心者殺しのCORS policyエラー
私はCORSを理解してませんし、理解できる気がしません。(偉そうにいうことではないですが)

以前X版を作っていたときは問題なかったのでもうこれはcdn.bskyのせいと決めつけました。

このエラーの解消は諦め、サーバーを立ててそこ経由で取得ができるんじゃない?
と調べていたらそれがリバースプロキシでした。


reverse-proxy.png


浅知恵の猿知恵でしたが試したところ上手く行きましたので記念に紹介したいと思います。

OSはAlpine Linux(Cloud RunにデプロイするDocker内)
WebサーバアプリはNginxです。

Nginx Configファイル作成

最初にリバースプロキシを行うためのNginxのConfigファイルを用意しておきます。
なぜNginxかは触ったことがあったからでして、apacheでもできると思います。

設定方法はこちらを参考にしました。


今回はこのような設定にしました。※ファイル名は拡張子が.confならなんでもよいです

proxy_test.conf
server {

    listen       8080;
    server_name  _;

    location / {

    	add_header Access-Control-Allow-Origin "*";
        add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
        add_header Access-Control-Allow-Headers "Origin, Authorization, Accept";
        add_header Access-Control-Allow-Credentials true;
	
    	rewrite /(.*) /$1  break;
    
    	proxy_pass https://cdn.bsky.app/;

    }
}

add_headerはリバースプロキシと関係ありません。(私のやりたかったCORSエラー回避のため追加しています。)関係あるのはrewriteとproxy_passだけです。

rewriteで正規表現を使いマッチしたURLを書き換えることができ、proxy_passは転送先となります。
今回は自分宛(リバースプロキシサーバ、以下代理サーバとします)に来たリクエストを


"https://(代理サーバのホスト名)/img/~~~.jpeg"

"https://cdn.bsky.app/img/~~~.jpeg"


と変換することを目的としています。

rewrite /(.*)とすることで「/img/~~~.jpeg」がマッチ。それを$1で受け取ることができ、proxy_passに設定した https://cdn.bsky.app/ につなげて転送できるといった感じです。

今回はホスト名以下をまるごと使うのでこうしましたが、/img/以下だけを使いたい場合は「rewrite /img/(.*) /$1 break;」とすればマッチした部分だけ利用することができます。

意図した通り動くかはこの後のDockerで確認しながら作成した方がよさそうです。
※proxy_passに"/"を含むかどうかで変わるなど、かなり緻密な点があります

Cloud Run用 Dockerfile作成

この設定ファイルを基にどこかにNginxが動くサーバーが必要となります。
今回はCloud Runを利用することにしました。

なぜCloud Runのメリットはドメインの用意が不要なことです。Compute Engineなどの仮想サーバではドメイン設定をしないとIPむき出しの接続となり、それはそれで問題になるかと思います。

ドメイン不要がどういうことかはこの後見て頂けたらと思います。

Cloud Runを利用するまでは以下を参考にさせて頂きました。


流れとしましてはCloud Buildでコンテナイメージを登録しておき、それを基にCloud Runを作成するような感じとなります。

ということでまずDockerファイルをこしらえます。

Dockerファイル
FROM nginx:stable-alpine3.20

ADD proxy_test.conf /etc/nginx/conf.d/

RUN rm /etc/nginx/conf.d/default.conf

EXPOSE 8080

CMD ["nginx", "-g", "daemon off;"]

ベースイメージはnginx(タグは無くても大丈夫だと思います。)にして、先ほど作成したconfigファイルを「/etc/nginx/conf.d/」下に置きデフォルトのconfigファイルを削除しています。※ベースイメージのLinuxの種類によって異なる可能性があります

ポートはCloud Runのデフォルトの8080にしておき、Dockerでnginxを動かす際のお約束CMD ["nginx", "-g", "daemon off;"] としておきます。

あとはこれをデプロイ。Cloud Runを使うまでにあるとおり最初にCloud Buildにイメージをビルドします。先ほどのDockerファイルがあるフォルダからpowershellで以下を実行します。

powershell
$PROJECT_ID="rational-oasis-XXXXXXXX"  # 自身のプロジェクトID

gcloud config set project $PROJECT_ID

gcloud builds submit --tag gcr.io/$PROJECT_ID/proxy_test  # proxy_testは適当です

あとはCloud Runにデプロイするだけです。このままコマンドでできるようですが、私はコンソールから操作します。
Snapshot_182.PNG

コンテナイメージのURLはgcr.io/(プロジェクト名)/(ビルド名)です。サービス名は適当です。

Snapshot_183.PNG

Snapshot_184.PNG

インスタンスの最小数が0の場合、起動に時間がかかります。ただこれを1以上にすると料金が変わるので注意してください。

Snapshot_185.PNG

Snapshot_186.PNG


成功しましたらエンドポイントURLが出てきます。これが最初に言っていたドメインが不要ということです。

https://cdn.bsky.app を発行された https://proxy-test-1043149056745.asia-northeast1.run.app に置き換えれば同じ画像を表示することができるようになります。

 
https://proxy-test-1043149056745.asia-northeast1.run.app/img/feed_fullsize/plain/did:plc:2et4xgrlwcqymiyjpvdv4yle/bafkreia7fdlsuaob47fjxy2umdnah6iuiqfy7wew6gg7ampwptwch6ughu@jpeg


https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:2et4xgrlwcqymiyjpvdv4yle/bafkreia7fdlsuaob47fjxy2umdnah6iuiqfy7wew6gg7ampwptwch6ughu@jpeg

※わかりづらいですが下の画像を上のURLからも表示できるようになるということです

おわりに

やっていて 「これってもしや違法なんじゃ…」 と思い "リバースプロキシ 違法" で検索すると「漫画村」が出てきました😅

「こんなことできるんだ!」と無邪気に使っていたら違法になるかもしれないので注意してください笑

0
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
0
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?