概要
前回はAzure Blob Storageに画像のアップロードを行った。
アップロードした画像を使いたいが、Azure Blob Storageの静的ホスティングで公開すると、Azure Static Web Appsとドメインが別になる。
同一オリジンポリシーにより、JSでのfetchができなかったり、キャンバスの汚染の問題があるため、これを解決したい。
Blob Storageの静的ホスティングはCORSをサポートしていないため、AWSでいうCloudFrontにあたるAzure CDNを使って解決することとする。
静的ホスティング
有効にすると、$webというコンテナが作成される。
ソースもコンテナに対応するように修正し、アップロードを試してみる。
export const useImageUploaderPageHooks = () => {
- const containerName = `images`;
+ const containerName = `$web`;
アップロードはうまく行った。
アクセスできないことの確認
次に、コードからアップロードしたファイルをダウンロードしようとしてみる。
const res = await fetch('https://hoge.z11.web.core.windows.net/fuga.png', {
mode: 'cors',
});
上記のコードだと、下記のエラーとなる。同一オリジンポリシー違反のため。
Access to fetch at 'https://hoge.z11.web.core.windows.net/fuga.png' from origin 'https://piyo.5.azurestaticapps.net' 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.
CDNの作成
下記のようにストレージアカウントの「セキュリティとネットワーク > Front Door と CDN」を選択。作成する。元のホスト名は静的Webサイトを選択。
なお、推奨されているAzure Front DoorとCDNを比較したが、Front Doorは機能が豊富でWAFが標準でついてくる代わりに価格が5000円~。お試しに払うには高いので今回はCDNを使う。
↑ 月20円 (1G/月) ↓月5000円(1G/月)
CDNの設定
作成したエンドポイントの「設定 > ルールエンジン」を選択。
「規則の追加」を押し、設定を追加する。
規則名 | wsa |
---|
条件:要求ヘッダー
ヘッダー名 | 演算子 | ヘッダー値 | 大文字と小文字の変換 |
---|---|---|---|
Origin | 次の値に等しい | https://piyo.5.azurestaticapps.net | 変換なし |
アクション:要求ヘッダーの変更
アクション | HTTPヘッダー名 | HTTPヘッダーの値 |
---|---|---|
追加 | cross-origin-resource-policy | cross-origin |
追加 | Access-Control-Allow-Origin | https://piyo.5.azurestaticapps.net |
動作確認
CDN経由のURLに書き換える
- const res = await fetch('https://hoge.z11.web.core.windows.net/fuga.png', {
+ const res = await fetch('https://moga.azureedge.net/fuga.png', {
mode: 'cors',
});
ここまでの設定をしたら、クロスオリジンでのCORS対応が完了し、画像がfetchできることを確認した。
参考
Azure Storage + Azure CDN でCORP対策を行う
追記:キャッシュを何とかしたい
画像を更新しても反映されないので、キャッシュを削除したくなりました。
CORS対応のアクセス(リクエストにOriginが含まれている)ではキャッシュが効かないようにする。
CDNファイルのキャッシュを無効にする
CDNはキャッシュのバイパスを設定する。
フロントエンド側で画像読み込み時にOriginリクエストをする
imgタグからの取得でもorigin
の要求ヘッダが入るように、crossOrigin
属性を追加する。*
- <img src={src} height={100} />
+ <img src={src} height={100} crossOrigin="anonymous" />
aタグでのダウンロードはOriginがつかないので置き換える
- <a href={`${zipUrl}`}>
<Button
icon="download"
style={{ marginLeft: '5px' }}
+ onClick={async () => {
+ const res = await fetch(`${zipUrl}`, { mode: 'cors' });
+ const blob = await res.blob();
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement('a');
+ a.href = url;
+ a.download = `${data.name}.zip`;
+ a.click();
+ }}
>
ユドナリウム用ZipDL
</Button>
- </a>