HTTPプロトコル解析
ISO-OSIの7層ネットワークモデル
- アプリケーション層 - ウェブサービスとエンドユーザーの間のインターフェース。以下のプロトコルがあります。 
- プレゼンテーション層 - データ表現、セキュリティ、圧縮。JPEG、ASCll、EBCDIC、暗号化フォーマットなど。 
- セッション層 - セッションの確立、管理、終了。対応ホストプロセス、ローカルホストとリモートホスト間の進行中のセッション 
- トランスポート層 - データを送信するためのプロトコル・ポート番号、フロー制御、エラー・チェックを定義します。プロトコルは、TCP UDP、パケットがネットワークカードを出ると、ネットワーク・トランスポート層に入ります。 
- ネットワーク・レイヤ 論理アドレス・アドレッシングを実行し、異なるネットワーク間のパス選択を可能にします。プロトコルは次のとおりです。 
- データリンク層 - 論理接続の確立、ハードウェアアドレスのアドレス指定、エラーチェックなどの機能。ビットをバイトとフレームに結合し、MACアドレスでメディアにアクセス。 
- 物理層 - 物理的な接続の確立、維持、切断。 
ストリーミング:ユニットの明確な分割はなく、前後の正しい順序のみが保証されます。
ポート:受信パケットは様々なアプリケーションに分配されます。
require('net'):ノード依存ライブラリ
パッケージ
IPアドレス
libnet/libpcap: libnet は IP パケットを構築して送信し、libpcap は NIC を流れる NIC からのすべてのパケットを取得します。
全二重チャンネルには優先順位関係はありませんが、HTTPはクライアントがリクエストを開始し、サーバーがレスポンスを返す必要があります。
サーバ側の環境準備
- POST / HTTP/1.1 - Request line 
- headers 
- field1=aaa&code=x%3D1 - body 
const http = require('http');
http.createServer((request, response) => {
 let body = [];
 request.on('error',(err) => {
 console.error(err);
 }).on('data',(chunk) =>{
 body.push(chunk.toString())
 }).on('end',()=>{
 body = Buffer.concat(body).toString();
 console.log('body:',body);
 response.writeHead(200,{'Content-T':'text/html'});
 response.end("<div style='width:200px;height:200px;background:red'>123</div>")
 })
}).listen(8080);
console.log('server started');
HTTPリクエストの実装
const net = require("net");
class Request {
 constructor(option) {
 this.method = option.method || 'GET';
 this.host = option.host;
 this.port = option.port || 80;
 this.path = option.path || '/';
 this.body = option.body || {};
 this.headers = option.headers || {};
 if(!this.headers["Content-Type"]){
 this.headers["Content-Type"] = "application/x-www-form-urlencoded"
 }
 if(this.headers["Content-Type"] ==="application/json"){
 this.bodyText = JSON.stringify(this.body)
 }else if(this.headers["Content-Type"] === "application/x-www-form-urlencoded"){
 this.bodyText = Object.keys(this.body).map(key => `${key}=${encodeURIComponent(this.body[key])}`).join('&')
 }
 this.headers["Content-Length"] = this.bodyText.length;
 }
 send(){
 return new Promise((resolve, reject) => {
 //.....
 });
 }
}
void async function () {
 let request = new Request({
 method: "POST",
 host: ".1",
 port: "8088",
 path: "/",
 headers: {
 ["X-Foo2"]: "customed"
 },
 body: {
 name: 'Midsummer'
 }
 })
 let response = await request.send();
 console.log(response);
}()
IV.書き込み関数を送信し、応答形式を理解します。
- state line HTTP/1.1 200 OK
- headers
- body
リクエストの送信
response
- レスポンスは分割して作成しなければならないので、ResponseParser で "組み立て" ます。
- ResponseParser は、ResponseText をセグメント化し、ステートマシンを使用してテキストの構造を分析します。
response body
- レスポンス本体はContent-Typeによって異なる構造を持つ可能性があるため、サブパーサーの構造を使用して問題を解決します。
- TrunkedBodyParserを例にとると、同じステートマシンがボディのフォーマット処理に使われます。




