【学習記録】『HTTPの教科書』第２章　読書メモ　〜N予備校の復習を添えて〜

【学習記録】『HTTPの教科書』第１章　読書メモ　〜N予備校の復習を添えて〜( https://qiita.com/Molly95554907/items/2e9c44a1402cb6e95e27 )の続き

<h5>第２章</h5>
・クライアント：テキストや画像などのリソースを欲しいと要求する側
・サーバー：リソースを提供する側

クライアントからリクエストが送られ、サーバーからレスポンスが返る形で通信が行われる

<h5>●リクエスト</h5>
例）
クライアント→HTTPサーバー

GET /index.html HTTP/1.1
Host:hackr.jp

これは「hackr.jp」というホストに、HTTPサーバーにある、「index.html」というリソースを出して、と要求している。

要求の対象となるリソース＝リクエストURI
ここでの「リクエストURI」はindex.html

↓
つまり・・・
<h6>サーバーにリクエストするリソースは、URLではなくURIと呼称する！</h6>
●URI：リソースを識別するための文字列全般を表す。
●URL：リソースの、ネットワーク上の場所を表す
<br>
サーバーに求めるのは、リソースそのものであり、リソースのネットワーク上の一では無い。
だから、サーバーにリクエストするリソースはURI
<br>


・冒頭の'GET'：サーバーに対する要求の種類（メソッド）。

リクエスト（GET /index.html HTTP/1.1）は、
「メソッド + URI + プロトコルバージョン（HTTPのバージョン）」で構成されている。

↓
<h5>●レスポンス</h5>
例）
HTTP/1.1 200 OK
Date: Tur, 10 Jul 2012 06:50:15 GMT
Content-Length: 362
Content-Type: text/html
```<html>
…
```

・ステータスコード：HTTPのバージョンは1.11／"200 OK"はリクエスト成功
・ヘッダーフィールド：レスポンスの作成日時、リソースのサイズと形式
・ボディ：リソースの本体
↓
HTTPのヘッダーにはリクエストの処理結果を表すステータスコードが含まれている。


●疑問点
サーバーにリクエストを行いレスポンスを返す、このコードはどうやったら見れるのか、どこで使われるのか？コンソールに打ち込んだりするものじゃなさそう。
HTTPヘッダとかは、実際どうやって調べるのか？Chromeのディベロッパーツール使ったら見れるのかな？


<h5>N予備校３章１１項「HTTPサーバー」</h5>
・Node.jsを使ってHTTPサーバーを作成する

```js
'use strict';
const http = require('http');
const server = http.createServer((req, res) => {
  res.writeHead(200, {
    'Content-Type': 'text/plain; charset=utf-8'
  });
  res.write(req.headers['user-agent']);
  res.end();
});
const port = 8000;
server.listen(port, () => {
  console.log('Listening on ' + port);
});
```
・HTTPモジュールを読み込む
参考：公式ドキュメント・HTTPモジュールについて（ https://nodejs.org/docs/v10.14.2/api/http.html#http_http_createserver_options_requestlistener ）

・httpモジュールの機能、http.createServerでサーバーを作成。
サーバーには、req(リクエストを表すオブジェクト引数)と、res(リクエストを表すオブジェクト引数)を受け取る無名関数を渡す。

サーバーにアクセスするとこの無名関数が呼び出される。

```
＜公式ドキュメントより＞ーーーーーーーーーーーーーーーーーーーーー
http.createServer（[options] [,requestListener]）

[options]オブジェクトに入力するものは、http.IncomingMessageクラスかhttp.ServerResponseクラス
・http.IncomingMessageクラス
「IncomingMessageオブジェクトにより作成されるhttp.Server、または http.ClientRequest最初の引数として渡される'request' と'response'、それぞれのイベント。応答ステータス、ヘッダー、データへのアクセスに使用できます。」

・http.ServerResponseクラス
「このオブジェクトは、ユーザーではなくHTTPサーバーによって内部的に作成されます。'request'イベントの2番目のパラメーターとして渡されます。」

[,requestListener]
Functionが入る

・戻り値：http.Serverクラスが戻り値として得られる

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
```
無名関数の中身：リクエストが来た際の処理
res.とは、レスポンスとして○○を行う、ということ

res.writeHead(200, {
    'Content-Type': 'text/plain; charset=utf-8'
  });

HTTPヘッダーに「200というステータスコードを、'text/plain; charset=utf-8'というコンンテンツタイプで書きこむ」処理

```
＜公式ドキュメントより＞ーーーーーーーーーーーーーーーーーーーーー
response.writeHead（statusCode [、statusMessage] [、headers]）

・statusCode <番号>
・statusMessage <文字列>
・headers <オブジェクト>

要求に応答ヘッダーを送信します。ステータスコードは、のような3桁のHTTPステータスコード404です。最後の引数headersは、応答ヘッダーです。オプションでstatusMessage、2番目の引数として人間が読める形式を指定できます。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
```
res.write(req.headers['user-agent']);

・write 関数： HTTP のレスポンスの内容を書き出す

ここではリクエストヘッダの user-agent の中身を、レスポンスの内容として書き出している

```
＜公式ドキュメントより＞ーーーーーーーーーーーーーーーーーーーーー

response.write（chunk [、encoding] [、callback]）

chunk <文字列> | <バッファ>
encoding <string> デフォルト： 'utf8'
callback <機能>
戻り値：<ブール値>

初めてresponse.write()呼び出されると、バッファされたヘッダー情報と本文の最初のチャンクがクライアントに送信されます。2回目のresponse.write()呼び出しでは、Node.jsはデータがストリーミングされると想定し、新しいデータを個別に送信します。つまり、応答は本文の最初のチャンクまでバッファリングされます。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
```

res.end();で応答終了

```
＜公式ドキュメントより＞ーーーーーーーーーーーーーーーーーーーーー

response.end（[data] [、encoding] [、callback]）
このメソッドは、すべての応答ヘッダーと本文が送信されたことをサーバーに通知します。そのサーバーは、このメッセージが完了したと見なす必要があります。メソッドはresponse.end()、各応答で呼び出される必要があります。

dataが指定されている場合、呼び出しのresponse.write(data, encoding)後にが続くのと同じ response.end(callback)です。

場合はcallback、指定された応答ストリームが終了したとき、それが呼び出されます。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
```

const port = 8000;
server.listen(port, () => {
  console.log('Listening on ' + port);
});


 HTTP が起動するポートを「8000」と宣言。
サーバーを起動して、起動した際に実行する関数を渡す。

```
＜公式ドキュメントより＞ーーーーーーーーーーーーーーーーーーーーー
server.listen（）
接続を待機しているHTTPサーバーを起動します。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
```

※公式ドキュメントを読んでもいまいち何を言っているのか理解できない・・・！用語がわかっていないからかな？調べた先にさらにわからない用語・概念が出てくるからなかなか理解できない。今後の課題。

<h5>●リクエストURIでソースを識別する</h5>
HTTPはURI（Uniform Resource Identifiers）を使って、インターネットのリソースを特定する。
URIのおかげで、インターネット上のどの場所にあるリソースでも呼び出せる。

クライアントがリソースを呼び出す際には、リクエスト送信時にリクエスト中にURIを、「リクエストURI」と呼ばれる形式で含める必要がある。

●リクエストURIの指定方法
・URIを全てリクエストURIに含める

GET　http://~~~~jp/index.html HTTP/1.1

↓
http://~~~~.jp/index.html htmlをリクエスト

・Hostヘッダーフィールドにネットワークロケーションを含める

GET /index.html HTTP/1.1
Host: ~~~~.jp 

<h5>●HTTPのメソッド</h5>
○GET
リソースの取得

リクエストURIで識別されるリソースを要求する。リソースがテキストならテキストを返す。リソースがプログラムなら実行結果を出力する。

○POST
エンティティボディの転送

クライアントからサーバーへエンティティボディ（データ）を送る

○PUT
ファイルの転送

・HEAD
メッセージヘッダーの取得

GETと似た機能だが、メッセージボディは返さない。URLの有効性やリソースの更新時間を確かめるために使う

○ DELETE
ファイルの削除

リクエストUPIで指定されたリソースをサーバーから削除する

・OPTION
サポートしているメソッドの問合せ

つまり、どのメソッドならサーバーに対して実行できるか（GETとHEADはできる、DELETEはできない、など）

・TRACE

経路の調査
通常は使われない。クロスサイトトレーシング（XST）のリスクもある

Webサーバーに接続した後、自分に通信を折り返してもらう。リクエスト先で、どのようにリクエストが加工されているかを調べる。

・CONNECT

プロキシにトンネル接続の確立を要求する。主に、SSLやTLSなどのプロトコルで暗号化したものをトンネルさせる為に使う。


<h5>N予備校３章１3項「HTTPのメソッド」</h5>

HTTPのメソッドのうち
・GET
・POST
・PUT
・DELETE

の４つは、ソフトウェアが情報の永続化を行う際の操作に欠かせない。

永続化に必要な操作
↓
CRUD
 Create (生成)・Read (読み取り)・Update (更新)・Delete (削除) 

<h6>ソフトウェアの要件定義時には、必ずこれらの機能に漏れがないか確認！！！</h6>
（ステートチャート図を使うと、データのまとまりの処理を可視化して、機能の実装漏れを防げる）


○GETメソッド
指定なしにブラウザで情報取得する

○POSTメソッド
情報を投稿する

○POSTメソッド
情報を追加、更新する

○DELETEメソッド
情報を削除する


<h5>N予備校３章１4項「HTMLのフォーム」</h5>
WEBサーバーの実装

```js
'use strict';
const http = require('http');
const server = http.createServer((req, res) => {
  const now = new Date();
  console.info('[' + now + '] Requested by ' + req.connection.remoteAddress);
  res.writeHead(200, {
    'Content-Type': 'text/html; charset=utf-8'
  });
```
・HTTPメソッドを作成
・http.createServerメソッドを使いサーバーを作成。

```js
  switch (req.method) {
    case 'GET':
      const fs = require('fs');
      const rs = fs.createReadStream('./form.html');
      rs.pipe(res);
      break;
```
・HTTPメソッドの'GET'でアクセスされた場合の処理

この授業で作成したfs モジュールを読み込む。
fsモジュールのcreateReadStream でファイル（'./form.html）を読み込み、ストリームを作成し、変数rsに代入する。
レスポンスのオブジェクト res に対して pipe 関数でパイプする。

※パイプとは
pipe という関数を利用すると、
HTTP のレスポンスのコンテンツとして、ファイルの内容をそのまま返すことができる


```js
    case 'POST':
      let rawData = '';
      req.on('data', (chunk) => {
        rawData = rawData + chunk;
      }).on('end', () => {
        const decoded = decodeURIComponent(rawData);
        console.info('[' + now + '] 投稿: ' + decoded);
        res.write('<!DOCTYPE html><html lang="ja"><body><h1>' +
          decoded + 'が投稿されました</h1></body></html>');
        res.end();
      });
      break;
    default:
      break;
  }
}).on('error', (e) => {
  console.error('[' + new Date() + '] Server Error', e);
}).on('clientError', (e) => {
  console.error('[' + new Date() + '] Client Error', e);
});
```
・HTTPメソッドの'POST'メソッドでアクセスされた場合の処理

decodeURIComponent 関数を利用して、 URL エンコードされた値を 元のものに直す。

「yaki-syabu=焼き肉」か「yaki-syabu=しゃぶしゃぶ」のどちらに投稿されたのかをログに残す。

投稿内容をHTMLの見出しにして返す。

```js

const port = 8000;
server.listen(port, () => {
  console.info('[' + new Date() + '] Listening on ' + port);
});
```

8000番のポートにサーバーを立てる


○課題
・「データをエンコードする」ってどういうこと？
・授業でやった上記の処理について、一行ずつ「これは何をしているのか？」を答えようとしても答えられない。そのコードの行で使われているオブジェクト、メソッドを公式ドキュメントで調べたとしても理解に限界があるというか・・・。何かアプリを作りながら、N予備校の動画を見て二周目をしたい