CORSに関するまとめメモ(FastAPIをつかってみた)

##はじめに
現在、練習としてFastAPIを使って簡単なアプリケーションを作成しています。
チュートリアルを進めていく中で以下のようなコードを記述しました。

```python
origins = [
  "https://localhost:3000",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_creditionals=True,
    allow_methods=["*"],
    allow_headers=["*"]
)
```

コードを書いたはいいものの意味がわからなかったので、調べたことをまとめていきながら上記のコードの内容を理解していきたいと思います。

##本文に移る前に
今回、CORSについて調べるにあたり、こちらの[なんとなく CORS がわかる...はもう終わりにする。](https://qiita.com/att55/items/2154a8aad8bf1409db2b)を参考にさせていただきました。
ありがとうございます。
あくまでこの記事は、上記の記事を元にわからない部分を付け足しながら書いた記事です。
現時点での自分の理解度で書いているため間違った記載があることも十分考えられるので、その際はご指摘いただけると助かります。

##結論
- CORSに関する設定をしている

CORS??何それ??状態だったのでCORSからまとめていきます。

##CORSとは？

- CORSはCross Origin Resource Sharingの略。 日本語訳では「オリジン間リソース共有」。

> オリジン間リソース共有Cross-Origin Resource Sharing (CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組み(MDNより)

またまた、ちんぷんかんだったので、オリジンについて調べていきます。
※ひたすらここから用語の深堀がはじまっていきます。

###オリジンとは？

> ウェブコンテンツのオリジンOriginは、ウェブコンテンツにアクセスするために使われる URL のスキーム (プロトコル)、 ホスト (ドメイン)、 ポート によって定義されます。スキーム、ホスト、ポートがすべて一致した場合のみ、二つのオブジェクトは同じオリジンであると言えます。

オリジンとは、URLのスキーム、ホスト、ポートの３つの組み合わせのことみたいです。
では次にURLについてみていきます。


###URL(スキーム、ホスト、ポート)について
こちらは例をあげてみていきます。
 
```
　①　　 ②　 　  ③　　　 ④　　⑤
http://www.example.com:80/user/1
```
1. スキーム・・・利用するプロトコルを指定(http)
 - プロトコル・・・ネットワークに接続された機器同士が通信する時のあらかじめ決められたルール
2. ホスト・・・サービスを提供する役割のコンピューターのこと(www)<br>ドメインの前にドット( . )区切りで表される
3. ドメイン・・・IPアドレスを人間が認識しやすくしたもの(example.com)　
<br>＊一意でなければならない
	- IPアドレス・・・インターネット上に存在するサーバーを特定して、接続するための個別の識別番号
4. ポート番号・・・コンピューターが提供するサービスを特定する番号（通常は省略されている。）(80)
<br>＊ドメインがマンションの住所、ポート番号が部屋番号のイメージ
5. パス・・・接続したサーバーのファイルやディレクトリの場所を示すもの(user/1)

オリジンとは、先ほども書いた通り、URLのスキーム、ホスト、ポートの３つの組み合わせのことです。
では、上記のURLの説明を元に、異なるオリジンと同じオリジンの例を挙げてみます。   


|<b>異なるオリジン</b>|例|異なる点|
|---|---|---|
|スキームが異なる|http\://qiita.com/hoge<br>https\://qiita.com/hoge|http or https|
|ホストが異なる|http://www.example.com<br>http://news.example.com|www or news|
|ポートが異なる|http\://localhost:3000/<br>http\://localhost:8000/|3000 or 8000|


|<b>同じオリジン<b/>|
|---|
|http://hoge.example.com/<br>http://hoge.example.com:80/<br>http://hoge.example.com/example.html<br>|

なんとなくオリジンについてわかってきました。
ここでもう一回CORSの説明に戻ってみます。
> オリジン間リソース共有Cross-Origin Resource Sharing (CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組み(MDNより)

つまり「オリジン間リソース共有」という訳にあるように、情報を異なるオリジン間で共有することができるようにする仕組みのことをCORSというみたいです。
オリジンについて意味を知ることで、CORSについてもちんぷんかんの状態から脱することができました。
ちなみに読みは”シーオーアールエス”もしくは”コルス”と読むらしいです。

#CORS の必要性
CORSがどういうものかがなんとなくわかってきたので、次は必要性やそのしくみについてみていきたいと思います。
そもそもWebは、<b>同一生成元ポリシー（Same-Origin Policy）</b>と呼ばれるものを実施していて、オリジンが違うとその情報源はクロスオリジンになりアクセスがブロックされます。


###なぜ同一生成元ポリシーが必要なの？？
これはセキュリティーの観点から必要になってきます。同一生成元ポリシーがない場合を考えてみます。
例えばユーザーがECサイトにログインしている状態で別オリジンの悪意あるサイトを閲覧した場合、ECサイトに登録された個人情報を悪意あるサイトから取得されて悪用されてしまう危険性があります。
そのほかにも様々な脆弱性を防ぐ目的で同一生成元ポリシーが必要とされています。

[こちらの記事](https://qiita.com/att55/items/2154a8aad8bf1409db2b#cors-%E3%81%AE%E5%BF%85%E8%A6%81%E6%80%A7)で詳しく書かれています。


悪質な攻撃から守るために、同じオリジンからのリソースにのみアクセスできるようにしていますが、実際のアプリケーションでは他のオリジンにアクセスする場合も存在します。（フロントがサーバー側のAPIとやり取りするのもクロスオリジンです）
このような場合に、クロスオリジンのアクセスを安全に許可するためにブラウザはCORSを利用します。


##CORSの仕組み

次に、CORSの仕組みについてみていきたいと思います。
CORSの仕組みは以下のようになっています。

1. フロントサイドがクロスオリジンにリクエストを送る
2. クライアントは自動的にHTTPリクエストにOriginというヘッダを追加する。Originヘッダの値は、リクエストがどこから来たのかを表す。
3. クロスオリジンへのアクセスを許可するためには、サーバー側で設定を行う。（サーバーのレスポンスに許可するためのヘッダを追加する）
4. リクエストで送られてきたOriginヘッダの値とレスポンスのヘッダの値が等しいかどうかをチェック
5. 4がOKならクロスオリジンのリソースに対してもアクセスができるようになる。

サーバーサイドでCORSに関する設定を行っておいて、フロントサイドからリクエストが来た時に、設定した内容をレスポンスとして返して、その両者の情報を突合してアクセスしていいかどうかのチェックをしているという流れですね。

確かにこの流れであれば、[結論](https://qiita.com/drafts/c1c8aad33876656a3d50/edit#%E7%B5%90%E8%AB%96) で書いた、「CORSに関する設定をしている」という文章に関しても納得できました。


ここまで、CORSについて確認をしてきました。
では、本来の目的である、FastAPI上でのCORSの設定コードを再度みていきたいと思います。


##fastAPIでのCORS設定

今までで説明したCORSについて、FastAPIではCORSMiddlewareを使用することで設定ができます。

```python
from starlette.middleware.cors import CORSMiddleware


origins = [
  "https://localhost:3000",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_creditionals=True,
    allow_methods=["*"],
    allow_headers=["*"]
)
```

- allow_origins=origins
    - クロスオリジンを許可するオリジンのリストを配列で指定する。
      今回はフロント側(react)からのアクセスを許可したいので、https\://localhost:3000を指定。　　　　　　　　　　　　　　
- allow_creditionals=True
    -  Cookieの共有を許可するかどうか。デフォルトはFalse。
- allow_methods=["*"]　   
    - 許可するHTTPメソッドを指定する。デフォルトはGET<br>
    アスタリスク( * )にすることで全てのHTTPメソッドを許可する。
- allow_headers=["*"]      
    - オリジン間リクエストでサポートするHTTPリクエストヘッダーのリスト。デフォルトは [] 。<br>
      ['*']を使用して、すべてのヘッダーを許可できる。<br>
      CORSリクエストでは、 Accept 、 Accept-Language 、 Content-Language 、 Content-Type ヘッダーが常に許可される。

allow_headersに関してはあまり理解ができていないのですが、とりあえず許可するHTTPリクエストヘッダーを指定しているのだと思います。

以上が、CORSについてのまとめと、FastAPIでのCORS設定についてでした！

##最後に
実際にコードを書いて、いろいろわからない単語を調べていくことでなんとなくではありますが、理解を進めることができました。
わからないことが少しでもわかるようになると楽しいですね！
あと、やはりアウトプットは自分の理解を深めるためにも大切だと感じました。
ここまで読んでいただいてありがとうございました。

##参考記事、書籍
- [fastapi CORSドキュメント](https://fastapi.tiangolo.com/ja/tutorial/cors/)
- [URIを理解する](https://qiita.com/sumin/items/429d1422df003eb41534)
- [ドメイン名とは](https://www.cman.jp/network/term/domain/)
- [MDN Originドキュメント](https://developer.mozilla.org/ja/docs/Glossary/Origin)
- [MDN CORSドキュメント](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)
- [なんとなく CORS がわかる...はもう終わりにする。]( https://qiita.com/att55/items/2154a8aad8bf1409db2b)
- [CORSの仕組みをGIFアニメで分かりやすく解説](https://coliss.com/articles/build-websites/operation/work/cs-visualized-cors.html)
- 小林恭平・坂本陽, イラスト図解式 この一冊で全部わかるWeb技術の基本, NRIネットコム株式会社, 2017.