Web システム、HTTP の基本（初心者向け）

# はじめに
この記事は **Web 3層アーキテクチャ**や **HTTP 通信**について簡単にまとめた内容となっており、以下の記事の続編である。

https://qiita.com/yukitkns/items/72c8a988a3f616b0150c

# Web システムの構成
Web システム開発において、現在は以下のようなシステム構成を採用することがほとんどである。

![スクリーンショット 2024-02-17 4.00.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/a96e5c79-5558-4d6c-98cf-ecaf887ba354.png)


上図のように「**プレゼンテーション層**」「**アプリケーション層**」「**データ層**」の3層に分割し、それぞれ役割を明確にする。
このような構成を「**Web 3層アーキテクチャ**」「**Web 3層構造**」などと呼ばれる。

3層に役割を明確化することで、各層が疎結合化※1し、
+ **特定のサーバの負担を軽減**
+ **機能変更を行う場合、他の層まで影響を及ぼさない**
+ **障害の発見と対処が容易化**

といった事が可能となる。

※1...システムやコンポーネント間の依存度が低く、変更が容易な状態を指す。

# Web サーバ
Web サーバは、Web ブラウザ等のクライアントソフトウェアに対して、HTML※2 などで書かれたデータを配信するソフトウェアのことである。
もしくは、そのソフトウェアを導入されたサーバ自体を指すこともある。

※2...Hyper Text Markup Language の略で、Webページを構築するための標準的なマークアップ言語の1つ。

元々3層アーキテクチャという考え方はなく、Webサーバ層のみの構成であった。
そして従来の Web サーバの機能は以下のみで、実にシンプルなものであった。
* **HTTP リクエストにて指示された、Web サーバ内に存在する HTML ファイルの内容を、HTTP レスポンスとして返す。**
* **Web ブラウザは返ってきた HTTP レスポンスの内容を表示する。**

しかし、インターネットが普及するにつれ、下記のような要望が出てきた。
* **Web ページを閲覧するユーザーごとに表示させる内容を変えたい。**
* **インターネットを介した業務処理をユーザーに提供したい**

ユーザーがアクセスしてきたタイミング、もしくは入力内容によって、Web ページを動的※3に変化させる仕組みが Web サーバに必要となった。
そのための仕組みとして、最初は「**CGI（Common Gateway Interface）**」が提供された。

※3...要求に応じて内容を変えること。

CGI は、Web ブラウザからパラメータと共に送られた要求に対し、Web サーバがプログラムを呼び出して処理を実行、パラメータに応じた結果(HTML)を返すというやり取りを行う。

![スクリーンショット 2024-02-17 4.44.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/fa934aad-4968-81d6-57d6-ba4c9d699d7a.png)

また、CGI のデータのインプットは標準入力、アウトプットは標準出力を使用するため、標準出力・標準入力が扱える言語であれば、どんな言語でも開発可能であるという柔軟性も持ち合わせていた。

そのため CGI を使用した動的ページの生成は比較的容易で、広く普及するツールとなった。

しかし、その反面、実行時の負荷が大きいため処理が遅い、CGI プログラムの不具合により予期せぬ動作をした場合、その影響が Web サーバに及んでしまう等のデメリットが露呈した。

さらに、高度な処理を行うプログラムをより安全・高速に動作させる仕組みが求められるようになり、それに応じて Web サーバの機能も拡張されていった。

こうなってくると、Web サーバに機能を追加していくよりも、Web サーバは従来のシンプルな機能のみを提供し、プログラムを動かすサーバは別に分けた方が良いという考え方が広まっていった。

そこで新たに登場したサーバが「**アプリケーションサーバ**」である。

# アプリケーションサーバ
（Web）アプリケーションサーバとは、**Web アプリケーションを実行するための機能を提供しているソフトウェアのこと**である。

アプリケーションサーバは、ユーザーからのリクエストに応じて、アプリケーションの実行や処理を行うもので、
オープンソース※4なものから商用製品まで多数存在しており、機能は多岐に渡る。

※4...ソフトウェアのソースコードが一般に公開され、誰でも閲覧・使用・変更・配布が許可される形式の開発アプローチやライセンスを指す。

以下が代表的なアプリケーションサーバである。
(内容が多いので、各アプリケーションサーバの用途の詳細説明は割愛する)
| 製品名 | 開発元 | 用途 |
|:-:|:-:|:-:|
| Apache Tomcat  | Apache Software Foundation  | 軽量でJavaサーブレットやJSPの実行環境を提供する  |
| Nginx  | Nginx,Inc.  | Webサーバとして広く使用され、リバースプロキシや負荷分散なども可能  |
| Microsoft Internet Information Services(IIS)  | Microsoft Corporation  | Windows環境で動作し、ASP.NETや静的なウェブコンテンツを提供  |
| WildFly(JBOSS)  | Red Hat  | Java EE (Jakarta EE) アプリケーションの実行環境を提供  |
| IBM WebSphere Application Server  | IBM  | 企業向けのJava EEアプリケーションサーバ  |
| Oracle WebLogic Server  | Oracle Corporation  | 大規模で高可用性なJava EEアプリケーションのデプロイと実行  |
| Jetty  | Eclipse Foundation  | EmbeddableなJava HTTPサーバおよびServletコンテナ  |
| GlassFish  | Eclipse Foundation (以前は Oracle Corporation)  | Java EEアプリケーションサーバ  |
| Resin  | Caucho Technology | Java EEアプリケーションの実行環境
| LiteSpeed Web Server  | LiteSpeed Technologies  | ハイパフォーマンスなウェブサーバおよびリバースプロキシ  |

# HTTP リクエスト / HTTP レスポンス
<b>HTTP（Hyper Text Transfer Protocol）</b>とは、HTML 文書や画像等のデータを Web サーバと Web ブラウザ間でやり取りするために使われるプロトコルで、TCP/ IP ※5の上位レイヤープロトコルに位置する。
Web ページを見る際に Web ブラウザの検索タブに <b>URL（Uniform Resources Locator）</b>という文字列を入力するが、この URL から HTTP リクエスト（※後述）が作られる。

※5...インターネット上のデータ通信における標準プロトコルスイート（集まり）。

HTTP は現在でも広く使われているプロトコルで、最大の特徴は**ユーザーからのリクエストに対して、サーバはレスポンスを返す、それだけで処理が完結するシンプルさ**である。

下記の画像が含まれたサンプル Web ページを例にすると、
![スクリーンショット 2024-02-17 5.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/d63b9274-8459-5905-a14a-979bff5e00ac.png)

1. **ユーザーはリクエストメソッドに「GET」を指定し、Web サーバへ 取得したいWeb コンテンツ が存在するディレクトリとファイル名等の情報を含んだ HTTP リクエストを送信する**
2. **Web サーバは 1 に対する HTTP レスポンスを Web ブラウザへ返す**
2. **HTTP レスポンスを受信した Web ブラウザは、その内容の中身を解析、このページに画像ファイルが含まれていることを判定**
2. **Web ブラウザは 3 で取得するための要求として、再度 HTTP リクエストを送信する**
2. **Web サーバはその画像ファイルをエンコード※6して、HTTP レスポンスとして返す**

※6...データや情報を特定の形式や規則に変換するプロセス。

![スクリーンショット 2024-02-17 8.05.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/278b74de-e78f-d8ff-c89c-d536744bcc7e.png)

なお、HTTP は「**ステートレス**」と呼ばれる1回のやりとりごとに通信を終了させる方式を取っており、「**クッキー（後述）**」等を使用して問題を解決する工夫が施されている。

## HTTP リクエスト
ブラウザから送信される HTTP リクエストは次の要素で構成されている。
* **リクエストライン**
* **HTTP リクエストヘッダー**
* **HTTP リクエストボディ（メッセージボディ）**

![スクリーンショット 2024-02-17 8.19.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/8af9168f-43bd-ac69-6bb1-c4b4627340ef.png)

この中で「**HTTP リクエストボディ**」にはHTTP リクエストのメッセージ本体が入る。

### リクエストライン
リクエストラインは下記要素で構成される。

+ **HTTP バージョン**
+ **リクエストの種類（メソッド）**
+ **リクエストURI（データを取得する Web サーバのパス）**

その中でメソッドは Web サーバへの命令を表し、下記のような種類がある。
| メソッド | 種類 |
|:-:|:-:|
| **GET**  | クライアントがサーバの情報を取得する(リソース取得要求） |
| **HEAD**  | サーバ情報のヘッダー部分を取得する（リソース取得要求（ヘッダーのみ）） |
| **POST**  | クライアントからサーバに情報を送る（データの送信と処理の要求）  |
| **PUT**  | クライアントがサーバにファイルを保存する（ファイルの転送）  |
| **DELETE**  | クライアントがサーバのファイルを削除する（ファイルの削除）  |
| **TRACE**  | リクエストをそのままレスポンスとして返す（経由サーバのトレース）  |

メソッドは多くの場合「**GET**」となり、この場合、HTTP リクエストではデータ本体が格納されるリクエストボディは空になる。
（メソッドが「**POST**」の場合、リクエストボディにデータ本体が格納される。）

### HTTP リクエストヘッダー
HTTP リクエストヘッダーは、HTTPリクエストボディの前に格納される、
各種の状態を示す情報が入れられている部分である。

HTTP リクエストヘッダーの代表的な要素として次のようなものがある。
<dl>
  <dt>User-Agent</dt>
  <dd>Web ブラウザの種類やOSの情報。アクセスしているのが Web ブラウザはなく検索エンジンのクローラ※7の場合、「Googlebot」などの名前が入る。</dd>
  <dt>Referer</dt>
  <dd>どのページから発生したリクエストなのかを示す。例えば、ページ A にあるリンクをクリックしてページ B にいった場合、ページ B への HTTP リクエストにリファラとしてページ A が入る。</dd>
  <dt>If-Modified-Since（ファイルの変更日付） / If-None-Match（管理情報）</dt>
  <dd>余分なトラフィック※8を Web サーバに送信させないために、ブラウザは一度表示したデータを「<b>ローカルキャッシュ</b>」として保存しておき、同じデータは再取得しない。その際、ローカルキャッシュのデータが更新されていないかをチェックするために、上記のヘッダーを加えておく。</dd>
  <dt>Cookie</dt>
  <dd>Web ブラウザに保存されているクッキー情報。</dd>
  <dt>Accept（コンテンツの形式） / Accept-Language（言語） / Accept-Encoding（圧縮方法） / 
 Accept-Charset（文字コード）</dt>
  <dd>クライアントがサーバに対して特定のコンテンツの形式や言語、文字コード※9などを指定するために使用される。</dd>
</dl>

※7...インターネット上に公開されているテキスト・画像・動画などの情報を自動で収集し、データベースに保管するプログラム
※8...インターネット上で通信されるデータ。
※9...テキストデータをコンピュータが扱える形式にエンコードするための規則や方式。

### クッキー
メッセージのシンプルさを保つため、HTTPはステートレス型を採用しており、1回の通信ごとに完結する仕組みとなっている。
そのため、ショッピングサイトのような「選択」「購入」「支払い手続き」など、数ステップに分かれている場合、それぞれの操作が同じユーザーによる一連の操作なのか判別することが不可となっている。
そこで「**クッキー**」と呼ばれる技術を使用して、一連の操作かどうかを判別できるようにしている。

![スクリーンショット 2024-02-19 16.42.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/515b7b50-fcbc-4c5b-1707-c2b349e3bbf8.png)

![スクリーンショット 2024-02-19 16.48.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/d57bc95e-ae49-166b-599e-0020628c3462.png)


## HTTP レスポンス
サーバから返された HTTP レスポンスは次の要素で構成されている。
+ **ステータスライン**
+ **HTTP レスポンスヘッダー**
+ **HTTP レスポンスボディ（メッセージボディ）**

![スクリーンショット 2024-02-17 12.36.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/98231b7b-c63a-b200-1d82-7313d471d185.png)

HTTP リクエストと同じく、「**HTTP レスポンス**」にはレスポンスメッセージ本体が格納される。

### ステータスライン
ステータスラインは下記要素で構成される。

* **HTTP バージョン**
* **ステータスコード**
* **テキストフレーズ（理由フレーズ）**

ステータスコードは、サーバからクライアントに返される3桁のコードで、現在の状態（ステータス）を表す。
HTTP バージョンとして差はあるが、ステータスコードとして HTTP / 1.1 では主に下記のような種類がある。
| コード | 意味 | 内容 |
|:-:|:-:|:-:|
| **1XX**  | 肯定先行  | 正しいコマンドを受け付けて処理中  |
| **2XX**  | 肯定完了  | 正しいコマンドを受け付けて処理完了  |
| **3XX**  | 肯定中間  | 正しいコマンドを受け付けて、次に別のコマンドを要求  |
| **4XX**  | 一時否定完了  | 誤ったコマンドを受け付けて、再送を要求  |
| **5XX**  | 否定完了  | サーバの状態によりコマンドの受付不可  |

| コード | 応答フレーズ | 内容 |
|:-:|:-:|:-:|
| **200**  | OK  | 正常にリクエストを受付  |
| **201**  | Created  | 正常にリクエストを作成  |
| **204**  | No Content  | 正常にリクエストを受付、応答するリソースが無し  |
| **301**  | Movenent Permanently  | リクエストされたリソースが Location ヘッダーで示された URL へ完全移動  |
| **304**  | Not Modified | リソースは未更新  |
| **400**  | Bad Request | 開始行、メッセージヘッダーの構文にミスがあり、受取不可  |
| **401**  | Unauthorized | 認証が必要  |
| **403**  | Forbidden | アクセスが拒否  |
| **404**  | Not Found | リソースの不在 |
| **405**  | Method Not Allowed | メソッドの実行を拒否 |
| **409**  | Conflict | 現在のリソースと状態とリクエストが競合 |
| **500**  | Internal Server Error | サーバ内部のエラー |
| **501**  | Not Implemented | コマンドを実行する機能が不在 |
| **503**  | Service Unavailable | サーバが一時的に過負荷またはメンテナンス中で、リクエストの処理不可 |
| **504**  | Gateway Timeout | ゲートウェイ※11がタイムアウト |

※11...異なるネットワーク間での通信を中継する機器。

例えば、存在しないリソースのURLを指定した場合、ステータスコード **404** が Web サーバから返される。

### HTTP レスポンスヘッダー
HTTP レスポンスヘッダーは、HTTP レスポンスボディ（データ本体）の前に格納される、各種の状態を示す情報が入れられている部分である。
HTTP レスポンスヘッダーの代表的な要素として次のようなものがある。

<dl>
  <dt>コンテンツタイプ（Content-Type）</dt>
  <dd>本文のデータ型を示す。例えば、HTML、JSON、画像など。</dd>
  <dt>再利用期限（Expires）</dt>
  <dd>取得したデータを再度サーバに問い合わせしなくてもブラウザが再利用して良い期限（有効期限）</dd>
  <dt>データの最終更新日時（Last-Modified）</dt>
  <dd>コンテンツの最終更新時刻</dd>
  <dt>エンティティ情報（ETag）</dt>
  <dd>ブラウザのキャッシュされたコンポーネントと Web サーバ上の元々の情報が一致しているかどうかを決定するための情報</dd>
  <dt>キャッシュ制御（Cache-Control や Pragma）</dt>
  <dd>ブラウザや通信の橋渡しを行うプロキシが、データのキャッシュをどう扱うかの情報</dd>
  <dt>接続状況（Connection）</dt>
  <dd>クライアントとサーバ間の接続の管理に関する情報。接続の保持（<b>keep-alive</b>）、接続の切断（<b>close</b>）を選択可能。HTTP / 1.1 ではデフォルトで <b>keep-alive</b> が行われる</dd>
  <dt>移動先(Location）</dt>
  <dd>リダイレクト先を示す情報。移動先となる URL が格納され、そのURLからデータを取得するように指示する</dd>
</dl>

## Chrome デベロッパーツールで HTTP メッセージを確認
ここでは「Google Chrome」を利用してWeb ブラウザと Web サーバが HTTP メッセージをやり取りする様子や、クッキーの受け渡しについて確認する方法について紹介する。

最初にブラウザ内右上の 3点リーダーから「**その他のツール**」→「**デベロッパーツール**」をそれぞれ選択する。
![スクリーンショット 2024-02-19 14.19.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/eec625c7-1bcc-a624-67d5-a1ca411a4487.png)

Macの場合、「**Network**」タブを選択、「Cmd」＋「R」でアクティビティの更新を行います。
![スクリーンショット 2024-02-19 14.23.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/fc0feb61-98ad-834b-d918-ff291085d421.png)

「**Headers**」タブを選択後、HTTP リクエストの中身をブラウザ上で確認することができる。
![スクリーンショット 2024-02-19 14.30.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/c4c73377-5cbf-a211-5fde-42884f6f818b.png)

下にスクロールすると、HTTP レスポンスの中身も確認することができる。
![スクリーンショット 2024-02-19 14.35.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/ac5fbf3a-691a-ad50-a2d9-d3e7d8276c71.png)

「**Cookies**」タブを選択することで、やり取りされたクッキーを確認することができる。
![スクリーンショット 2024-02-19 14.40.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1430519/03622926-138c-3ab6-d63f-ecd4e2197044.png)

## 補足：HTTP バージョン
HTTP バージョンには主に「**HTTP / 1.0**」と「**HTTP / 1.1**」の2つのバージョンがある。
1.0 では、ハイパーテキストを取得するための単純なメソッドと応答コードのみで構成されており、Web ページや画像を連続して取得するには、何回もコネクションを作成して要求（リクエスト）と応答（レスポンス）を繰り返す必要があった。

しかし、 1.1 ではメソッドや応答コードが拡張されただけでなく、**connection ヘッダを用いて複数の複数の HTML や XML ドキュメント、画像などのファイルを 1 回のやり取りでまとめて取得できるようになった**。

更に一度取得した Web ページを一時保存しておく**キャッシュ機能**なども追加されている。
**キャッシュ機能により、Web ページの更新をプロトコルで確認できるうえ、一度取得した Web ページと内容が変わらない場合には、ネットワークから再度ダウンロードする必要がないため、通信量が少なく済み、結果として高速表示が可能となった**。

このように 1.1 が主流となったわけだが、近年の Web ページコンテンツの複雑化により、2015年に HTTP / 2、2018年には HTTP / 3 が公開され、主流が急速に変わりつつある。
両バージョンは Web ページ高速化機能が備わっており、Web ページの表示の遅延を解消するものとして開発されたが、**HTTP メッセージ自体の文法などは 1.1 から変わっていないため**、まずは 1.1 についてから知る、という内容で問題ないかと思われる。


## 参考文献
https://www.amazon.co.jp/gp/product/B0CSX88WVT/ref=ppx_yo_dt_b_d_asin_title_351_o00?ie=UTF8&psc=1

https://www.sbcr.jp/product/4815623333/