今度こそクロスオリジンとCORSを完全に理解する

### クロスオリジンとCORSについて
この二つ、特にCORSについて、今まで何度も調べているが、なかなか覚えられない。
たぶん理解が足りてないので、今回はChatGPTも使い、完全に理解して二度と調べないためにこの記事を残します。
※似た様な記事を何度か見かけて目を通しましたが、結局読むだけでは理解しきれなかったので、この記事を書いているためパクリではないです。
あと自分が理解するために書いているので、少々蛇足的な部分もあります。

#### 1. **オリジンとは？**
まず、オリジンという言葉について、開発の現場でもあんまり使わなくないですか？
簡単にいうとウェブブラウザーが異なるサイトを区別するための概念とのことで、プロトコル（HTTPやHTTPS）、ホスト（ドメイン）、ポート番号の３つ組み合わせです。

1. ***プロトコル***: ウェブサイトにアクセスするための<font color="SlateBlue">**通信規約**</font>。例えば、http:// や https:// があり、ウェブサイトにアクセスする際のルールを示します。

2. ***ホスト***: ウェブサイトが存在する場所を示すもので、一般的には<font color="SlateBlue">**ドメイン名**</font>と呼ばれ、例えば、example.com や subdomain.example.com のようなものです。

3. ***ポート番号***: ウェブサイトが利用している通信の出入り口を指定する番号。通常、ウェブブラウザーは80番ポート（HTTP）や443番ポート（HTTPS）をデフォルトで使用します。

これらの要素が合わさって、オリジンが定義されます。例えば、https://example.com:443 は完全なオリジンであり、プロトコルが https://、ホストが example.com、ポート番号が 443 です。同じオリジン内では、情報の共有やセキュリティ制約が適用されることになります。

ここまではいつも調べて「へー」と思っていましたが、ホストとドメインの区別がしっかり理解できてない気がしたので、ついでにWebサイトとURLの整理もまとめてChatGPTに聞いてみたらすごく分かり易く教えてくれました。

>Webサイトは、ウェブ上で利用可能なコンテンツやページの集合体を指します。
URL（Uniform Resource Locator）は、ウェブページやリソースの特定のアドレスを示すもので、プロトコル（httpやhttpsなど）、ホスト（ウェブサイトが配置されている場所を指定するドメイン）、リソースのパスなどで構成されます。
ホストはURLの一部で、具体的にウェブサイトが配置されている場所を指し示します。
ドメインはホストの一種であり、ウェブサイトやサービスの識別に用いられ、通常、ウェブサイトの名前として認識されます。
例えば、ウェブサイト「www.example.com」の場合、URLはそのウェブページのアドレスを示し、ホストは「example.com」であり、ドメインも同じく「example.com」となります。

要は、ホストがサーバーの場所、ドメインが識別子ということだと理解しました。

#### 2. **同一生成元ポリシー (SOP) とは？**
ブラウザーが異なるオリジンからの直接リソースアクセスを制限するセキュリティポリシー。
JavaScriptなどのクライアント側コードは同一オリジン内でのみ実行される。

SOP：Same-Origin Policy
オリジンが同じリソースのみアクセス可能というポリシーのこと

#### 3. **クロスオリジンの問題とその理由**
クロスオリジンの問題は、SOPによって異なるオリジン間での直接通信が制限されること。
これはブラウザーがセキュリティを保つための仕組みで、異なるオリジンからのリソースへのアクセスが阻止される。

ポイントは<font color="Orange">**ブラウザ側で制限**</font>しているという点
ここを押さえておくとこの後の理解がしやすい

#### 4. **CORSの役割と仕組み**
CORS（Cross-Origin Resource Sharing）は、クロスオリジン通信を許可するための仕組み。
サーバーはリクエストに対して特定のHTTPヘッダーを返し、ブラウザーに許可されたオリジンからのアクセスを許可する。

サーバー側でHTTPヘッダーに情報を登録し、ブラウザ側での対象リソースへの許可するということで理解した。

#### 5. **CORSの設定とブラウザー動作**
実際にCORSを設定する場合、サーバー側では、`Access-Control-Allow-Origin`ヘッダーを使用して許可するオリジンを指定。
ブラウザーはリクエスト時にこのヘッダーを確認し、許可されたオリジンからのリクエストにのみレスポンスを返す。

ここで、`Access-Control-Allow-Origin`ヘッダー具体的な設定例を上げておく

1.全てのオリジンを許可する場合
```
Access-Control-Allow-Origin: *
```
2.特定のオリジンを許可する場合
```
Access-Control-Allow-Origin: https://example.com
```
3.複数のオリジンを許可する場合
```
Access-Control-Allow-Origin: https://example.com, https://subdomain.example.com
```


### 具体的な例題と応用方法

#### 例題 1: クロスオリジンリクエストのブロック解除
例えば、あるオリジン(`https://example.com`)からAPI(`https://api.example.com/data`)へアクセスする場合のクロスオリジンリクエストがブラウザーでブロックされる。
サーバー側でAPIリクエストのレスポンスに `Access-Control-Allow-Origin: https://example.com` を含めることで、このリクエストを許可する。

[3.クロスオリジンの問題とその理由](#3.-クロスオリジンの問題とその理由)のポイントにも書いたが、判断するのはブラウザ側ということ。
この場合、APIサーバーからオリジンへのレスポンスヘッダーに情報を登録し、最終的にブラウザ側でアクセス可能か判断することになる。

#### 例題 2: JavaScriptからの外部API利用
JavaScriptで `fetch` を使って外部APIにアクセスしようとすると、SOPによってブロックされる。
サーバーがCORS設定を持つ場合、ブラウザーは外部APIへのアクセスを許可し、データを取得できるようになる。

これも例題１と同じ要領

### 応用方法

#### 応用方法 1: カスタムヘッダーの使用
一部のリクエストには、カスタムHTTPヘッダーが必要な場合がある。
サーバー側で `Access-Control-Allow-Headers` を使ってブラウザーに許可するカスタムヘッダーを指定することができる。

#### 応用方法 2: プリフライトリクエスト
クライアントが一部のメソッド（例えば、POSTやDELETE）を使ってリクエストを送る場合、ブラウザーは事前にOPTIONSメソッドを使ってサーバーに対して許可を問い合わせる。
サーバーはこのプリフライトリクエストに対して、許可情報を含んだレスポンスを返すことができる。

### 最後に
今回の記事はChatGPTに以下のスクリプトを投げて得られた回答をもとに書きました。

~~~
クロスオリジンとCORSの説明を2000字以上で丁寧に
5つのポイントに分けて
初心者でも分かり易く
HTTPの知識も絡めて説明して
上記にプラスして、具体的な例題と応用方法を2つずつ上げてみて
~~~

AIすごい👍
わからないことが出てきたらまた調べて書こうと思います。

今回の記事でクロスオリジンとCORSについて完全に理解できました。
記事を読んでいただいた方も、読んで理解しきれない時は自分で書いてみることをお勧めします。