レビュー用資料 - ryhara/Webserv GitHub Wiki

以下にレビューで説明が必要な項目についてまとめる

手順的に必要なこと

  • homebrewでsiegeをinstall
  • ソケット上の全てのread/recv/write/sendを調べ、エラーの場合クライアントが削除されているかどうか
  • 全てのread/recv/write/sendを調べ、戻り値が正しくチェックされているかどうか
  • これらの操作後にerrnoがチェックされた場合は0
  • select() (または同等のもの) を経由せずにファイル記述子を書き込んだり読み取ったりすることは、厳密に禁止されています。
  • ステータスコードが正しいかどうか
  • 異なるポートで複数のサーバーをセットアップする
  • 異なるホスト名で複数のサーバーをセットアップする。 curl --resolve example.com:80:127.0.0.1 http://example.com/
  • クライアントの本文を制限する curl -X POST -H "Content-Type: plain/text" --data "BODY IS HERE write something shorter or longer than body limit"
  • サーバー内で別のディレクトリへのルートを設定する
  • ディレクトリを要求した場合デフォルトのファイルを設定する。
  • 特定のルートに対して受け入れられるメソッドのリスト(GET, POST, ...)を設定する。
  • telnet, curlを用いたテスト
    • GET, POST, DELETEのテスト
    • UNKNOWN リクエストでクラッシュしない
    • ステータスコードが正しいか
    • ファイルをアップロードして、それを返す
  • CGIのテスト
  • ブラウザでの確認
  • 複数ポートでブラウザで確認
  • 異なる構成で共通のポートを使用して複数のサーバーを同時に起動する。動作する場合は構成の1つが機能していないのにサーバーが動作する理由を答える。(できればこれは実行できないほうが良いかも)
  • siegeを用いたストレステスト、メモリリーク、ハング接続がないか

解説が必要なこと

HTTPサーバーの基本的な説明

ウェブサーバーとは

image

  • ハードウェアの観点 ソフトウェアやコンポーネントファイル(HTMLや画像など)を格納しているコンピューター
  • ソフトウェアの観点 ホストにあるファイルに対する、ユーザーのアクセスを制御するプログラムなどの集まり。 HTTPサーバーは最小限の部品である。コンテンツをユーザーの端末に配信する。

HTTPについて

HTTPはHTMLなどのリソースを読み取るためのプロトコル。 HTTPはTCPまたあ暗号化されたTCPであるTLSを使用して送信されるアプリケーション層のプロトコルだが、理論上は信頼性のある任意のトランスポート層プロトコルを使用できる。 HTTPはコネクションベースであるTCP標準に依存する。

クライアントがサーバーと通信する時以下の段階を踏む

  1. TCPコネクションを開く
  2. HTTPメッセージを送信する。 メッセージの形式
GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
  1. サーバーから送信されたレスポンスを読み取る レスポンスの形式
HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html

<!DOCTYPE html...(ここに、リクエストした 29769 バイトのウェブページが来ます)

I/O多重化に何を使用したか

select

select(同等なもの)がどのように機能するか

select(同等なもの)を1つだけ使用しているかどうか、サーバーの受け入れとクライアントの読み/書きをどのように管理したか

コードベースで説明

Defence

allow methodについて

すべての一般用サーバは、 GET および HEAD をサポートしなければならない。 他のメソッドのサポートは、 どれも任意選択である。

異なるホスト名で複数のサーバーをセットアップ

例えば、 http://www.example.org/pub/WWW/ 用の生成元サーバへ向けた GET 要請 は,次で始まることになろう:

GET /pub/WWW/ HTTP/1.1
Host: www.example.org
  • Setup multiple servers with different hostnames 異なるホスト名で複数のサーバーをセットアップする。 curl --resolve example.com:80:127.0.0.1 http://example.com/

keep-alive

HTTP/1.1 では、 持続的な接続 は,既定で利用できる — これは、 単独の接続越しに,複数の[ 要請や応答 ]を運べるようにする。 HTTP 実装は、 持続的な接続をサポートするべきである。 受信者は、[ 最も近過去に受信したメッセージ ]内の[ プロトコルバージョン, および[ 在るならば Connection ヘッダ ]]に基づいて,[ 接続が現在の応答の後にも持続することになるかどうか ]を決定する:

"close" 接続オプションが在るならば、 持続しない。

他の場合, 受信したプロトコルは HTTP/1.1 (以上のバージョン)ならば、 持続する。

telnetで空行を送った場合

堅牢性の観点からは、[ request-line を受信して, 構文解析する ]ことを期待しているサーバは、[ request-line に先立って受信した空行 ]を少なくとも 1 行以上は無視するべきである。

よって、ただの空行はエラーと判定しても問題ないと考えるが、リクエストラインを読んでいない状態で空行が来た場合は何もせずにリクエストラインを読むようにしている。

Hostヘッダー

subjectにてデフォルトの設定を使うように書いてあったので、ポート番号が指定されていないHostヘッダに関しては対応していない

Hostヘッダがない場合はerror

Host リクエストヘッダーは、リクエストが送信される先のサーバーのホスト名とポート番号を指定します。

ポート番号が指定されなかった場合は、要求されたサービスの既定のポート(例えば HTTPS の URL であれば443、 HTTP の URL であれば 80)とみなされます。

Host ヘッダー項目はすべての HTTP/1.1 リクエストメッセージで送信する必要があります。 HTTP/1.1 リクエストメッセージに Host ヘッダー項目がなかったり、二つ以上あったりした場合は 400 (Bad Request) ステータスコードが返されることがあります。

Transfer-Encoding, Content-Length

Transfer-Encoding

サーバは、[ Content-Length, Transfer-Encoding ]両者を包含する要請に対しては: 却下しても,あるいは Transfer-Encoding のみに則って処理してもよい。 いずれにせよ,攻撃の可能性を避けるため、 当の要請に対し応答した後には,接続を close しなければならない。

却下するが、接続を続けることにした。