telnetでHTTP通信(GET,POST)をやってみる
フィヨルドブートキャンプのプラクティスで、telnetでHTTP通信してみたよーって話。
ホスト名はどこまで?
telnetを使ってHTTPメッセージを出すのは、ブラウザでポチポチして情報を取得していたのを、telnetのコマンドとして要求するようにするみたいなイメージでいた。
で、とりあえず試してみたのが下記コマンド。(リクエストメッセージのフォーマットに沿って、改行もしっかり入れた。)
% telnet dummy-bootcamp-fjord-jp.herokuapp.com 80 Trying 174.129.128.48... Connected to dummy-bootcamp-fjord-jp.herokuapp.com. Escape character is '^]'. GET /articles HTTP/1.1
GET /articles HTTP/1.1
を叩いて、しばらく待っていたけど何も変化しなくて、コネクションがクローズされてしまった😅何で??ってなったので、プラクティスの質問やネットを漁ってみると、リクエストのヘッダーフィールドを入力しないといけなかった(HTTP入門にも書いてあった😅)。必須だったのはHost:
だったので入力して再度実行。
GET /articles HTTP/1.1 Host: http://dummy-bootcamp-fjord-jp.herokuapp.com/articles
そしたら、エラーが出てコンテンツがないという意味の404が出た。なんでや😭ってなってまた少し調査😅どうやらHost:
にはホスト名を入れないといけないということだった。
自分の理解としては、http://dummy-bootcamp-fjord-jp.herokuapp.com/articles
がホスト名と思っていたけど全然違った。URLは下記の構文になっている(参考:Web技術の基本)。
構成要素名 | 説明 |
---|---|
スキーム | プロトコルを指定する。 |
ホスト名 (ドメイン名) |
接続先のサーバを指定する。IPアドレスでの指定も可 |
ポート番号 | 接続先のサーバのポート番号を指定。 プロトコル毎に決まったポート番号(well-knownポート)があるものは省略可能。 |
パス名 | 接続先サーバ上のディレクトリやファイルを指定 |
補足として、ドメイン名とホスト名は厳密には意味が違うらしい。
- ドメイン名:ネットワークを特定する文字列
- ホスト名:ネットワーク上のコンピュータにつける識別用文字列
ホスト名とドメイン名をつなげたものをFQDN(Fully Qualified Domain Name:完全修飾ドメイン)といい、こいつでネットワーク上のコンピュータを特定できる。概念的なイメージを載せておく。
上記の通りなので、正しくは、dummy-bootcamp-fjord-jp.herokuapp.com
がホスト名なので、コマンドを叩いてみる。
ちゃんと取得できました🤗
HTTPのコンテンツサイズ
『POSTも大体同じでしょ』ということで、下記を実施してみた。article[title]
,articles[body]
の部分は、New Articleのページのソースを見て、入れるべき要素を特定した。
POST /articles/new HTTP/1.1 Host: dummy-bootcamp-fjord-jp.herokuapp.com article[title]=April&article[body]=20220402
すると、コンテンツが存在しないことを示す404
が出た。『/articles/newあるのになんでー???』となったが、QAによると、サーバ側で/articles/new
にそんなサービスを用意していないということっぽい(と自分としては理解した💦)。なので、/articles
に対して、POST
してみた。
POST /articles HTTP/1.1 Host: dummy-bootcamp-fjord-jp.herokuapp.com article[title]=April&article[body]=20220402
そしたら、リクエスト不正の400
のエラーコードが発生。ここも調べてみると、コンテンツサイズがないことが原因だった。コンテンツサイズが指定されていない場合、0byteのボディメッセージ扱いになる。POSTはデータを送信するメソッドなのに、データがないため不正リクエストになってしまったと考えられる。
というわけで、コンテンツサイズを入力すれば良い。が、コンテンツサイズってなんぼ入れればいいですか?となってしまった。コンテンツのサイズはメッセージボディなので、article[title]=April&article[body]=20220402
のサイズを確認すれば良い。アルファベットと記号は1文字1byteで表現できるので、上の場合43文字なのでコンテンツサイズも43byteにしてあげれば良い。コマンドを叩いてみる。
ちゃんと取得できました🤗
その後に、『コンテンツサイズなんて送るデータよりも大きければ名でもいいじゃね?』と思って色々試してみた。結果として、送りたいデータのサイズをちゃんと送るのが一番という気付きを得られた、、、そりゃそうか😅。理由は下記。
- 送りたいデータ>Content-Length:送るデータが途中で切られる
- 送りたいデータ<Content-Length:送るデータがContent-Lengthになるまでメッセージが送信されない