<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ja">
	<id>https://www.svgmap.org/wiki/index.php?action=history&amp;feed=atom&amp;title=CloudflareWorkers%E5%90%91%E3%81%91%E3%81%AECORS_Proxy%E5%AE%9F%E8%A3%85</id>
	<title>CloudflareWorkers向けのCORS Proxy実装 - 版の履歴</title>
	<link rel="self" type="application/atom+xml" href="https://www.svgmap.org/wiki/index.php?action=history&amp;feed=atom&amp;title=CloudflareWorkers%E5%90%91%E3%81%91%E3%81%AECORS_Proxy%E5%AE%9F%E8%A3%85"/>
	<link rel="alternate" type="text/html" href="https://www.svgmap.org/wiki/index.php?title=CloudflareWorkers%E5%90%91%E3%81%91%E3%81%AECORS_Proxy%E5%AE%9F%E8%A3%85&amp;action=history"/>
	<updated>2026-08-14T16:03:43Z</updated>
	<subtitle>このウィキのこのページに関する変更履歴</subtitle>
	<generator>MediaWiki 1.31.16</generator>
	<entry>
		<id>https://www.svgmap.org/wiki/index.php?title=CloudflareWorkers%E5%90%91%E3%81%91%E3%81%AECORS_Proxy%E5%AE%9F%E8%A3%85&amp;diff=2439&amp;oldid=prev</id>
		<title>Admin: /* 特徴 */</title>
		<link rel="alternate" type="text/html" href="https://www.svgmap.org/wiki/index.php?title=CloudflareWorkers%E5%90%91%E3%81%91%E3%81%AECORS_Proxy%E5%AE%9F%E8%A3%85&amp;diff=2439&amp;oldid=prev"/>
		<updated>2026-08-05T05:20:32Z</updated>

		<summary type="html">&lt;p&gt;‎&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;特徴&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;ja&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;← 古い版&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #222; text-align: center;&quot;&gt;2026年8月5日 (水) 05:20時点における版&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l6&quot; &gt;6行目:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;6行目:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* '''高速・省メモリ'''&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* '''高速・省メモリ'''&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: Cloudflare Workersのストリーム処理を活用し、データをバッファリングせずにそのまま転送します。&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: Cloudflare Workersのストリーム処理を活用し、データをバッファリングせずにそのまま転送します。&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* '''&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;強固なセキュリティ&lt;/del&gt;'''&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* '''&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;セキュリティ&lt;/ins&gt;'''&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: 事前に指定した許可ドメイン（Origin/Referer）からのアクセスのみを受け付けます。&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: 事前に指定した許可ドメイン（Origin/Referer）からのアクセスのみを受け付けます。&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: 意図しないセッションや認証情報の漏洩を防ぐため、デフォルトで &amp;lt;code&amp;gt;Cookie&amp;lt;/code&amp;gt; や &amp;lt;code&amp;gt;Authorization&amp;lt;/code&amp;gt; ヘッダーを遮断します。&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: 意図しないセッションや認証情報の漏洩を防ぐため、デフォルトで &amp;lt;code&amp;gt;Cookie&amp;lt;/code&amp;gt; や &amp;lt;code&amp;gt;Authorization&amp;lt;/code&amp;gt; ヘッダーを遮断します。&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: ターゲットサーバーにはプロキシ元の Origin/Referer を隠蔽し、ホットリンク対策によるアクセス拒否を回避します。&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: ターゲットサーバーにはプロキシ元の Origin/Referer を隠蔽し、ホットリンク対策によるアクセス拒否を回避します。&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* '''&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;柔軟な拡張性&lt;/del&gt;'''&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* '''&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;拡張性&lt;/ins&gt;'''&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: OPTIONSメソッド（プリフライト）に対応し、パラメータ指定で必要に応じたヘッダーのパススルーも可能です。&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;*: OPTIONSメソッド（プリフライト）に対応し、パラメータ指定で必要に応じたヘッダーのパススルーも可能です。&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;&amp;#160;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #222; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Admin</name></author>
		
	</entry>
	<entry>
		<id>https://www.svgmap.org/wiki/index.php?title=CloudflareWorkers%E5%90%91%E3%81%91%E3%81%AECORS_Proxy%E5%AE%9F%E8%A3%85&amp;diff=2438&amp;oldid=prev</id>
		<title>Admin: ページの作成:「= Cloudflare Worker CORS Proxy =  フロントエンドからのAPIリクエスト等で発生するCORSエラーを回避し、外部リソースを安全に取得する…」</title>
		<link rel="alternate" type="text/html" href="https://www.svgmap.org/wiki/index.php?title=CloudflareWorkers%E5%90%91%E3%81%91%E3%81%AECORS_Proxy%E5%AE%9F%E8%A3%85&amp;diff=2438&amp;oldid=prev"/>
		<updated>2026-08-05T05:19:55Z</updated>

		<summary type="html">&lt;p&gt;ページの作成:「= Cloudflare Worker CORS Proxy =  フロントエンドからのAPIリクエスト等で発生するCORSエラーを回避し、外部リソースを安全に取得する…」&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新規ページ&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= Cloudflare Worker CORS Proxy =&lt;br /&gt;
&lt;br /&gt;
フロントエンドからのAPIリクエスト等で発生するCORSエラーを回避し、外部リソースを安全に取得するために使用する専用プロキシ（Cloudflare Workers用）です。&lt;br /&gt;
&lt;br /&gt;
== 特徴 ==&lt;br /&gt;
* '''高速・省メモリ'''&lt;br /&gt;
*: Cloudflare Workersのストリーム処理を活用し、データをバッファリングせずにそのまま転送します。&lt;br /&gt;
* '''強固なセキュリティ'''&lt;br /&gt;
*: 事前に指定した許可ドメイン（Origin/Referer）からのアクセスのみを受け付けます。&lt;br /&gt;
*: 意図しないセッションや認証情報の漏洩を防ぐため、デフォルトで &amp;lt;code&amp;gt;Cookie&amp;lt;/code&amp;gt; や &amp;lt;code&amp;gt;Authorization&amp;lt;/code&amp;gt; ヘッダーを遮断します。&lt;br /&gt;
*: ターゲットサーバーにはプロキシ元の Origin/Referer を隠蔽し、ホットリンク対策によるアクセス拒否を回避します。&lt;br /&gt;
* '''柔軟な拡張性'''&lt;br /&gt;
*: OPTIONSメソッド（プリフライト）に対応し、パラメータ指定で必要に応じたヘッダーのパススルーも可能です。&lt;br /&gt;
&lt;br /&gt;
== 使い方 ==&lt;br /&gt;
プロキシURLの &amp;lt;code&amp;gt;file&amp;lt;/code&amp;gt; パラメータに、取得したいターゲットURLをURLエンコードして渡します。&lt;br /&gt;
※ 欠落を防ぐため、JavaScriptでは必ず &amp;lt;code&amp;gt;encodeURIComponent&amp;lt;/code&amp;gt; を使用してください（&amp;lt;code&amp;gt;encodeURI&amp;lt;/code&amp;gt; は不可）。&lt;br /&gt;
&lt;br /&gt;
=== 基本的なリクエスト ===&lt;br /&gt;
デフォルトではセキュリティを考慮し、認証情報やCookieを含めずにプロキシします。&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const targetUrl = &amp;quot;https://example.com/api/data&amp;quot;;&lt;br /&gt;
const proxyUrl = `https://your-worker.workers.dev/?file=${encodeURIComponent(targetUrl)}`;&lt;br /&gt;
&lt;br /&gt;
fetch(proxyUrl)&lt;br /&gt;
  .then(response =&amp;gt; response.json())&lt;br /&gt;
  .then(data =&amp;gt; console.log(data))&lt;br /&gt;
  .catch(error =&amp;gt; console.error(error));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== オプション付きリクエスト ===&lt;br /&gt;
以下のクエリパラメータを付与することで、ヘッダー情報の転送を許可できます。&lt;br /&gt;
* &amp;lt;code&amp;gt;pass_auth=1&amp;lt;/code&amp;gt; : クライアントからの &amp;lt;code&amp;gt;Authorization&amp;lt;/code&amp;gt; ヘッダー転送を許可する&lt;br /&gt;
* &amp;lt;code&amp;gt;pass_cookie=1&amp;lt;/code&amp;gt; : クライアントからの &amp;lt;code&amp;gt;Cookie&amp;lt;/code&amp;gt;、およびターゲットからの &amp;lt;code&amp;gt;Set-Cookie&amp;lt;/code&amp;gt; 転送を許可する&lt;br /&gt;
&lt;br /&gt;
例：フロントエンドから認証ヘッダーを送ってAPIを叩く場合&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const proxyUrl = `https://your-worker.workers.dev/?file=${encodeURIComponent(targetUrl)}&amp;amp;pass_auth=1`;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== ソースコード ==&lt;br /&gt;
以下のコードを Cloudflare Workers のスクリプトとしてデプロイして使用します。&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * ==============================================================================&lt;br /&gt;
 * Cloudflare Worker CORS Proxy (Edge-Optimized &amp;amp; Secure)&lt;br /&gt;
 * ==============================================================================&lt;br /&gt;
 *&lt;br /&gt;
 * 【目的】&lt;br /&gt;
 * 指定した許可ドメイン（自サイト等）からのみアクセス可能な専用のCORSプロキシ。&lt;br /&gt;
 * フロントエンドのCORSエラーを回避し、外部リソースやAPIを安全に取得するために使用する。&lt;br /&gt;
 *&lt;br /&gt;
 * 【狙い・特徴】&lt;br /&gt;
 * 1. 高速・省メモリ: &lt;br /&gt;
 * Cloudflare Workersのストリーム処理を活かし、データをバッファリングせずそのまま転送。&lt;br /&gt;
 * 2. 強固なセキュリティ: &lt;br /&gt;
 * - 許可された Origin/Referer からのアクセスのみを受け付ける。&lt;br /&gt;
 * - 意図しないセッションや認証情報の漏洩を防ぐため、デフォルトで Cookie / Authorization を遮断。&lt;br /&gt;
 * - ターゲットへはプロキシ元の Origin/Referer を隠蔽し、ホットリンク対策等の弾きを回避。&lt;br /&gt;
 * 3. 柔軟な拡張性: &lt;br /&gt;
 * OPTIONSメソッド（プリフライト）の動的許可や、必要に応じたヘッダーのパススルーに対応。&lt;br /&gt;
 *&lt;br /&gt;
 * 【使い方】&lt;br /&gt;
 * プロキシURLの `file` パラメータに、取得したいターゲットURLをエンコードして渡す。&lt;br /&gt;
 * ※ 欠落を防ぐため、必ず `encodeURIComponent` を使用すること（`encodeURI` は不可）。&lt;br /&gt;
 *&lt;br /&gt;
 * [基本リクエスト（デフォルト・セキュア）]&lt;br /&gt;
 * const targetUrl = &amp;quot;https://example.com/api/data&amp;quot;;&lt;br /&gt;
 * const proxyUrl = `https://your-worker.workers.dev/?file=${encodeURIComponent(targetUrl)}`;&lt;br /&gt;
 * fetch(proxyUrl) // ...&lt;br /&gt;
 *&lt;br /&gt;
 * [オプション（クエリパラメータ）]&lt;br /&gt;
 * - pass_auth=1   : クライアントからの `Authorization` ヘッダー転送を許可する&lt;br /&gt;
 * - pass_cookie=1 : クライアントからの `Cookie`、およびターゲットからの `Set-Cookie` 転送を許可する&lt;br /&gt;
 * * 例（フロントエンドから認証ヘッダーを送ってAPIを叩く場合）:&lt;br /&gt;
 * `https://.../?file=${encodeURIComponent(targetUrl)}&amp;amp;pass_auth=1`&lt;br /&gt;
 * ==============================================================================&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
export default {&lt;br /&gt;
	async fetch(request, env, ctx) {&lt;br /&gt;
		// ========================================================&lt;br /&gt;
		// 1. プロキシ対象URLとオプションの取得&lt;br /&gt;
		// ========================================================&lt;br /&gt;
		const url = new URL(request.url);&lt;br /&gt;
		const fileUrl = url.searchParams.get(&amp;quot;file&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
		// オプション（&amp;quot;1&amp;quot; の場合はヘッダーのパススルーを許可）&lt;br /&gt;
		const passAuth = url.searchParams.get(&amp;quot;pass_auth&amp;quot;) === &amp;quot;1&amp;quot;;&lt;br /&gt;
		const passCookie = url.searchParams.get(&amp;quot;pass_cookie&amp;quot;) === &amp;quot;1&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
		if (!fileUrl) {&lt;br /&gt;
			return new Response(&lt;br /&gt;
				JSON.stringify({ error: &amp;quot;Missing 'file' parameter with target URL.&amp;quot; }),&lt;br /&gt;
				{&lt;br /&gt;
					status: 400,&lt;br /&gt;
					headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;application/json; charset=utf-8&amp;quot; },&lt;br /&gt;
				}&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// ========================================================&lt;br /&gt;
		// 2. アクセス元（Origin/Referer）フィルター&lt;br /&gt;
		// ========================================================&lt;br /&gt;
		const allowedOrigins = [&lt;br /&gt;
			&amp;quot;svgmap.org&amp;quot;,&lt;br /&gt;
			&amp;quot;sssvgmap.stars.ne.jp&amp;quot;,&lt;br /&gt;
			&amp;quot;svgmap.github.io&amp;quot;,&lt;br /&gt;
		];&lt;br /&gt;
&lt;br /&gt;
		const origin = request.headers.get(&amp;quot;Origin&amp;quot;);&lt;br /&gt;
		const referer = request.headers.get(&amp;quot;Referer&amp;quot;);&lt;br /&gt;
		const clientUrl = origin || referer || &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
		let isAllowed = false;&lt;br /&gt;
		let allowOriginHeader = &amp;quot;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
		if (clientUrl) {&lt;br /&gt;
			try {&lt;br /&gt;
				const urlObj = new URL(clientUrl);&lt;br /&gt;
				const hostname = urlObj.hostname;&lt;br /&gt;
&lt;br /&gt;
				for (const domain of allowedOrigins) {&lt;br /&gt;
					if (hostname === domain || hostname.endsWith(&amp;quot;.&amp;quot; + domain)) {&lt;br /&gt;
						isAllowed = true;&lt;br /&gt;
						allowOriginHeader = origin || `${urlObj.protocol}//${hostname}`;&lt;br /&gt;
						break;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			} catch (e) {&lt;br /&gt;
				// URLのパース失敗時は弾く&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (!isAllowed) {&lt;br /&gt;
			return new Response(&lt;br /&gt;
				JSON.stringify({ error: &amp;quot;Access Denied: Invalid Origin/Referer&amp;quot; }),&lt;br /&gt;
				{&lt;br /&gt;
					status: 403,&lt;br /&gt;
					headers: { &amp;quot;Content-Type&amp;quot;: &amp;quot;application/json; charset=utf-8&amp;quot; },&lt;br /&gt;
				}&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// ========================================================&lt;br /&gt;
		// 3. CORS 共通処理 ＆ プリフライト（OPTIONS）応答&lt;br /&gt;
		// ========================================================&lt;br /&gt;
		// クライアントがカスタムヘッダーを送りたい場合に備え、リクエストされたヘッダーを動的に許可&lt;br /&gt;
		const requestedHeaders = request.headers.get(&lt;br /&gt;
			&amp;quot;Access-Control-Request-Headers&amp;quot;&lt;br /&gt;
		);&lt;br /&gt;
		const allowedHeaders = requestedHeaders || &amp;quot;Content-Type, Authorization&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
		const corsHeaders = {&lt;br /&gt;
			&amp;quot;Access-Control-Allow-Origin&amp;quot;: allowOriginHeader,&lt;br /&gt;
			&amp;quot;Access-Control-Allow-Methods&amp;quot;: &amp;quot;GET, POST, OPTIONS&amp;quot;,&lt;br /&gt;
			&amp;quot;Access-Control-Allow-Headers&amp;quot;: allowedHeaders,&lt;br /&gt;
		};&lt;br /&gt;
&lt;br /&gt;
		if (request.method === &amp;quot;OPTIONS&amp;quot;) {&lt;br /&gt;
			return new Response(null, { headers: corsHeaders });&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// ========================================================&lt;br /&gt;
		// 4. プロキシとしての Fetch 処理（ヘッダー検疫 ＆ ストリーム）&lt;br /&gt;
		// ========================================================&lt;br /&gt;
		const controller = new AbortController();&lt;br /&gt;
		const timeoutId = setTimeout(() =&amp;gt; controller.abort(), 30000); // 30秒タイムアウト&lt;br /&gt;
&lt;br /&gt;
		try {&lt;br /&gt;
			const fetchHeaders = new Headers(request.headers);&lt;br /&gt;
&lt;br /&gt;
			// ターゲットにプロキシ元の情報を漏らさない（アクセス拒否対策）&lt;br /&gt;
			fetchHeaders.delete(&amp;quot;Origin&amp;quot;);&lt;br /&gt;
			fetchHeaders.delete(&amp;quot;Referer&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
			// セキュリティ: Cookieの意図しない流出を防ぐ（オプションで許可可能）&lt;br /&gt;
			if (!passCookie) {&lt;br /&gt;
				fetchHeaders.delete(&amp;quot;Cookie&amp;quot;);&lt;br /&gt;
				fetchHeaders.delete(&amp;quot;Cookie2&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// セキュリティ: 意図しない認証情報の流出を防ぐ（オプションで許可可能）&lt;br /&gt;
			if (!passAuth) {&lt;br /&gt;
				fetchHeaders.delete(&amp;quot;Authorization&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// ユーザーエージェントを一般的なブラウザに偽装&lt;br /&gt;
			fetchHeaders.set(&lt;br /&gt;
				&amp;quot;User-Agent&amp;quot;,&lt;br /&gt;
				&amp;quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36&amp;quot;&lt;br /&gt;
			);&lt;br /&gt;
&lt;br /&gt;
			const fetchOptions = {&lt;br /&gt;
				method: request.method,&lt;br /&gt;
				headers: fetchHeaders,&lt;br /&gt;
				redirect: &amp;quot;follow&amp;quot;,&lt;br /&gt;
				signal: controller.signal,&lt;br /&gt;
			};&lt;br /&gt;
&lt;br /&gt;
			// POST等の場合、Bodyをストリームとしてそのまま転送&lt;br /&gt;
			if (request.method !== &amp;quot;GET&amp;quot; &amp;amp;&amp;amp; request.method !== &amp;quot;HEAD&amp;quot;) {&lt;br /&gt;
				fetchOptions.body = request.body;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// ターゲットURLへリクエスト&lt;br /&gt;
			const response = await fetch(fileUrl, fetchOptions);&lt;br /&gt;
			clearTimeout(timeoutId);&lt;br /&gt;
&lt;br /&gt;
			// ========================================================&lt;br /&gt;
			// 5. レスポンスヘッダーの構築と返却&lt;br /&gt;
			// ========================================================&lt;br /&gt;
			const responseHeaders = new Headers(response.headers);&lt;br /&gt;
&lt;br /&gt;
			// ターゲットからの Cookie をクライアントに書き込ませない（オプションで許可可能）&lt;br /&gt;
			if (!passCookie) {&lt;br /&gt;
				responseHeaders.delete(&amp;quot;Set-Cookie&amp;quot;);&lt;br /&gt;
				responseHeaders.delete(&amp;quot;Set-Cookie2&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// 事前に生成した CORS 許可ヘッダーを付与&lt;br /&gt;
			responseHeaders.set(&amp;quot;Access-Control-Allow-Origin&amp;quot;, allowOriginHeader);&lt;br /&gt;
&lt;br /&gt;
			// フロントエンドのJSが読み取れるように有用なヘッダーを公開&lt;br /&gt;
			const exposedHeaders = [&lt;br /&gt;
				&amp;quot;Content-Length&amp;quot;,&lt;br /&gt;
				&amp;quot;Content-Type&amp;quot;,&lt;br /&gt;
				&amp;quot;Content-Disposition&amp;quot;,&lt;br /&gt;
				&amp;quot;Last-Modified&amp;quot;,&lt;br /&gt;
			].join(&amp;quot;, &amp;quot;);&lt;br /&gt;
			responseHeaders.set(&amp;quot;Access-Control-Expose-Headers&amp;quot;, exposedHeaders);&lt;br /&gt;
&lt;br /&gt;
			// Content-Typeのフォールバック&lt;br /&gt;
			if (!responseHeaders.has(&amp;quot;Content-Type&amp;quot;)) {&lt;br /&gt;
				responseHeaders.set(&amp;quot;Content-Type&amp;quot;, &amp;quot;application/octet-stream&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			// ターゲットからのHTTPステータスとボディ（ストリーム）をそのまま返す&lt;br /&gt;
			return new Response(response.body, {&lt;br /&gt;
				status: response.status,&lt;br /&gt;
				statusText: response.statusText,&lt;br /&gt;
				headers: responseHeaders,&lt;br /&gt;
			});&lt;br /&gt;
		} catch (error) {&lt;br /&gt;
			clearTimeout(timeoutId);&lt;br /&gt;
&lt;br /&gt;
			if (error.name === &amp;quot;AbortError&amp;quot;) {&lt;br /&gt;
				return new Response(JSON.stringify({ error: &amp;quot;Request timed out.&amp;quot; }), {&lt;br /&gt;
					status: 504,&lt;br /&gt;
					headers: {&lt;br /&gt;
						&amp;quot;Content-Type&amp;quot;: &amp;quot;application/json; charset=utf-8&amp;quot;,&lt;br /&gt;
						...corsHeaders,&lt;br /&gt;
					},&lt;br /&gt;
				});&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
			return new Response(&lt;br /&gt;
				JSON.stringify({ error: `Internal Server Error: ${error.message}` }),&lt;br /&gt;
				{&lt;br /&gt;
					status: 500,&lt;br /&gt;
					headers: {&lt;br /&gt;
						&amp;quot;Content-Type&amp;quot;: &amp;quot;application/json; charset=utf-8&amp;quot;,&lt;br /&gt;
						...corsHeaders,&lt;br /&gt;
					},&lt;br /&gt;
				}&lt;br /&gt;
			);&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
		
	</entry>
</feed>