【Webを支える技術】Webについて学習したのでまとめました

## Webの用途
**Webサイト**
会社HPサイトなど主にページを表示する用途のサイト

**Webアプリケーション**
動画投稿サービスのyoutubeやAmazonのようなショッピングサイトなど

**ユーザインターフェースとしてのWeb**
GmailなどのSaaSやプリンタやハードディスクなど各種デバイスの設定画面など

**Web API**
プログラム用のインターフェイス

## Webを支える技術
**HTTP**
通信のためのルール(プロトコル)

**URI**
リソースを識別するためのID

**HTML**
情報を表示するための文書フォーマット

## 分散システム
複数のコンピューターやプログラムをネットワーク上に分散して配置し、1台のコンピュータで実行するよりも効率的に処理できるようにしたシステムのこと。Webは、世界中に配置されたサーバに世界中のブラウザがアクセスする分散システム。反対に一台の中央コンピューターがすべてを処理する形式を集中システムという。

# REST
RESTはWebのアーキテクチャスタイルのことで、複数のアーキテクチャに共通する性質、様式、作法を指す言葉。

## アーキテクチャスタイルとは
- 複数のアーキテクチャに共通する性質、作法、流儀 = 設計様式
- RESTによる実装例の１つが「Web」

|抽象化レベル|Webでの例|
|:--:|:--:|
|アーキテクチャスタイル|REST|
|アーキテクチャ|ブラウザ、サーバ、プロキシ、HTTP、URI、HTML|
|実装|Apache、Firebox、Chrome|

## Webにおけるリソース
- 世界中の無数のリソースは、それぞれURIで一意の名前を持つ
- URIを用いることで、プログラムはリソースが表現する情報にアクセスできる
- 複数のURIを持つリソースも存在する

## RESTを構成する6つのアーキテクチャスタイル
**① クライアント/サーバー**：UIと処理を分離する
これにより、クライアントをマルチプラットフォームにできる。例えばPCだけでなくスマホからもアクセスできるのはこの仕組みによる。

**② ステートレスサーバー**：クライアント状態をサーバーが管理しない
**③ キャッシュ**：サーバーから取得したリソースの再利用
**④ 統一インターフェース**：操作可能なインターフェースを限定
HTTP1.1ではGETやPOSTなど8個のメソッドだけが定義されており、拡張することができない。これは厳しい制約であるが、インターフェースの柔軟性に制限を加えることで全体のアーキテクチャがシンプルになり、クライアントとサーバの実装の独立性が向上する。

**⑤ 階層化システム**：システムを階層に分離
統一インターフェースにより、システム全体が階層化しやすく、サーバとクライアントの前にロードバランサーを設置して負荷分散をしたり、プロキシサーバーを設置してアクセスを制限できる。

**⑥ コードオンデマンド**：クライアントでDL(ダウンロード)&実行
JavaScriptやGoogle Fontなどがこれに該当する。

すべてを満たさないとRESTな設計でないということにはならない。例えば、Cookieを使ったセッション管理はユーザのログイン状態を管理するため、RESTのアーキテクチャスタイルに反したHTTPの拡張である。しかし、Cookieを使ったフォーム認証をやめるわけにはいかないのも事実である。そのため、ステートレスサーバの利点をあえて捨てることを理解した上で利用するようにする。

## URIの構文

```
https://torahack:pass@torahack.com:8000/posts?id=1&category=food#about
```

**URIスキーム**：https
通信プロトコルを指す。URLスキームとその後ろに続く部分は「://」で区切られる

**ユーザ情報**：qiita:pass
\<username>:\<password>形式

**ホスト名**：qiita.com
DNSで名前解決できるドメイン名 or IPアドレス

```
# 下記は別ホスト名の扱いになる
qiita.com
blog.qiita.com
```

**ポート番号**：8000
プロトコルで用いるTCPポート番号

**パス**：/posts
階層を表す、一意なリソースを指す

**クエリパラメータ**：id=1&category=food
名前=値形式の追加情報。クエリが複数ある場合、「&」でつなぐ

**URIフラグメント**：#about
Webページの内部の位置を指す

## URIと文字
URIではASCII文字(a-z A-Z 0-9 -.~:@!$&'())以外の文字を使うことができないため、日本語などの文字は%エンコーディングが必要になる。

```
https://torahack.com/あ → https://torahack.com/%E3%81%B2
```

## クールなURIの設計方法
「URIは変わらないべきである。変わらないURIこそが最上のURIである」という主張をクールなURIの定義とする。変わらずきれいなURIを設計するために下記4つを守るべきである。

1. プログラミング言語に依存した情報を含めない
2. メソッド名やセッションIDを含めない
3. URIはリソースを表現する名詞にする
4. なるべくシンプルかつ人間が読んで理解できるようにする

## URIの変更方法
どうしてもURIを変更したい時、301 Redirectを使ってできる限りリダイレクトするようにする。こうすると、ユーザを困らせないのはもちろんGoogleのページランクも引き継ぐことができ、SEOで有利になる。

```
301 Redirect → 恒久的なURIの変更
302 Redirect → 一時的なURIの変更
```

## URI設計のテクニック
- バージョン番号を含める(特にAPIの場合)

```
https://example.com/api/v1/~~
```
- 拡張子を用いて多言語対応のリソースを切り替える

```
https://torahack.com/portfolio.jp
https://torahack.com/portfolil.en
```

## URIの不透明性
URIをクライアント側で組み立てたり、拡張子からリソースの内容を推測したりできないことを「URIはクライアントにとって不透明である」という。

- URIからリソースの構造を推測できないようにすべき
- URIに拡張子を含めるとその言語で操作される可能性があるため避ける

## TCP/IPの4階層モデル
HTTPはTCP/IPをベースにしており、これらはインターネットの基盤を構成する重要なネットワークプロトコルである。

|階層|説明|例|
|:-:|:-:|:-:|
|アプリケーション層|アプリケーション毎の通信プロトコルを決定する層|HTTP, SSH, SMTP|
|トランスポート層|データ転送の抜け漏れをチェックする層|TCP, UDP|
|インターネット層|データを送るための層|IP|
|ネットワークインターフェース層|LANケーブルなどの物理的な層|イーサネット|

IPでは自分のネットワークインターフェースでデータを送り出すことだけを保証する。送り出したデータが、最終的に送り先に届くかまでは保証しない。その代わり、TCPが接続先とコネクションを張り、データの抜け漏れをチェックし、データの到達を保証する。

## HTTPメッセージ
http:// example.com/testに対する最小限のリクエストは次のようになる。

```text:リクエスト
GET /test HTTP/1.1  #リクエストライン（メソッド、リクエストURI、プロトコルバージョン）
Host: example.com  #ヘッダ（Hostヘッダは必須）
```
サーバーから返ってくるレスポンスは以下のようになる。

```text:レスポンス
HTTP/1.1 200 OK  #ステータスライン（プロトコルバージョン、ステータスコード、テキストフレーズ）
Content-Type: application/xhtml+xml; charset=utf-8  #ヘッダ

<html xmlns="http://www.w3.org/1999/xhtml>  #ボディ
...
```

## ステートレスとステートフル
**ステートレスの利点**
冗長でデータ量が多いが、サーバーがシンプルになる。そのため、接続先が増えるなどした場合でもサーバーを増設することでスケールさせやすい。

**ステートフルの利点**
認証など、サーバーに負荷がかかる処理を繰り返さないため、パフォーマンスが上がる。また、通信エラー発生時にサーバーはアプリケーションの状態を覚えているため対処が簡単になる。

## 主要なHTTPメソッド
HTTPメソッドは計8つだが主要なメソッドは下の4つである。

|メソッド|CRUD|役割|
|:-:|:-:|:-:|
|GET|Read|リソースの取得|
|POST|Create|子リソースの作成、リソースへのデータ追加|
|PUT|Create/Update|リソースの更新(存在しなければ作成)|
|DELETE|Delete|リソースの削除|

## べき等性と安全性
**べき等性**：ある操作を何回行っても結果が同じであること
**安全性**：操作対象であるリソースの状態を変化させないこと

|メソッド|特徴|
|:-:|:-:|
|GET|べき等かつ安全|
|POST|べき等でもなく安全でもない|
|PUT|べき等だが安全でもない|
|DELETE|べき等だが安全でもない|


## MIMEメディアタイプの指定
MIMEはMultipurpose Internet Mail Extensionsの略で電子メールから拝借してきた仕様である。Content-Typeヘッダでメディアタイプを指定する。(Type/Subtype形式) メディアタイプはcharsetパラメータを持てて、文字エンコーディングを指定できる。Typeがtextの場合、デフォルトでは日本語に対応していないエンコーディングがされ文字化けするため、必ず指定すること。

|主要なType|意味|type/subtype例|
|:-:|:-:|:-:|
|text|人が読んで直接理解できる|text/plain|
|image|画像データ|image/jpeg|
|audio|音声データ|audio/mpeg|
|video|動画データ|video/mp4|
|application|その他データ|application/json|

## 様々なヘッダ情報
|ヘッダ種別|例|意味|
|:-:|:-:|:-:|
|言語タグ|Content-Language: ja-JP|リソースを表現する自然言語|
|コンテントネゴシエーション|Accept: text/html, application/xml|クライアントが処理可能なメディアタイプ|
|ボディの長さ|Content-Length: 447|レスポンスボディのサイズ(byte)|
|チャンク転送|Transfer-Encoding: chunked|大きなデータをチャンク転送する|

## HTTP認証のためのヘッダ
Authorizationヘッダに認証情報を付与する。

```text:例
DELETE /test HTTP/1.1
Host: example.com
Authorization: Basic dXNlcjpwYXzd29ZA==
```

|認証方法|仕様|特徴|
|:-:|:-:|:-:|
|Basic認証|base64でエンコードされたユーザIDとパスワードを仕様|簡単にデコード可能なため、HTTPSによる暗号化が必須|
|Digest認証|デコードできないハッシュ化されたパスワードを仕様|メッセージは暗号化されないため、メッセージを暗号化したい場合はHTTPSによる通信暗号化が必須|

## キャッシュ
サーバーから取得したリソースをローカルストレージに蓄積し、再利用する手法のこと。そのキャッシュが有効な間、クライアントがサイドそのリソースにアクセスしようとしたときに再利用する。

|指定方法|目的|
|:-:|:-:|
|Cache-Control: no-store|キャッシュしない|
|Cache-Control: no-cache|キャッシュするが再検証する|
|Cache-Control: max-age=86400|相対的な有効期限を設定|
|Cache-Control: must-revalidate|必ず検証する|

- no-cacheとmust-revalidateの違い<br>
https://www.ryotosaito.com/blog/?p=264

以上になります。キャッシュについてはもう少し詳しく書きます。