🐕

Telnet で HTTP リクエストを送ってみた

2023/10/17に公開

はじめに

先月、一般社団法人の電子公告が Telnet で行われるということがありました(窓の杜によるニュース記事)。
Telnet というのは聞いたことはあるが実際に触ったことがなく、これを機に触ってみようと思います。

Telnet とは

あまり詳しくない分野でこういう説明をしだすと、四方八方からマサカリが飛んでくるので割愛します。
まぁ、 Telnet については各自で調べてください。

あと超絶余談ですが、広辞苑第七版によると割愛というのは「惜しいと思うものを思いきって手放したり省略したりすること」なので、本当に惜しいかどうかを考えて使うようにしています。
今回もめちゃくちゃ説明したかったです(棒)

今回やること

HTTP サーバに対して Telnet で通信を行います。なぜそれができるのかというと、実は Telnet は TCP の上で動いていて、 HTTP も TCP の上で動いているからです。
HTTP リクエストについては、1行目のリクエストラインと2行目から空白行までのリクエストヘッダー、空白行からのメッセージボディの3つから構成されます。

JSON 形式送るにはリクエストヘッダーに Content-Type: application/json を含めます。また Content-Length がないと、メッセージボディが 0 バイト扱いになるので、メッセージボディ送信前にレスポンスが返ってきちゃいます。

POST /super/ultra/yabai/yatsu HTTP/1.1
Content-Type: application/json
Content-Length: 13

{"hoge": 334}

GET などの場合はメッセージボディがないこともあります。その場合でもリクエストヘッダーの次の行は空白にしないといけないです。またリクエストヘッダーはなくても大丈夫です。

GET /super/ultra/yabai/yatsu HTTP/1.1

その形式で Telnet で送ればいいだけです。ねっ、簡単でしょ?

Telnet を触る

まず、小手調べに Google さんを見てみます。80番ポートに接続します。
(443番じゃないの?という人がいるかもしれないですが、Telnet は暗号化せず通信するものなので今回は80番使います)

$ telnet www.google.com 80
Trying 172.217.161.196...
Connected to www.google.com.
Escape character is '^]'.
GET / HTTP/1.1
Host: www.google.com

HTTP/1.1 200 OK
Date: Tue, 10 Oct 2023 11:59:09 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1

(省略)

ちゃんと 200 OK が返ってきましたね!今度は色々試せるようにローカルに HTTP サーバ立てて確認します。

ローカルに適当な php ファイルを置いて docker を起動してみます。

$ docker run -d -v ~/tmp:/var/www/html -p 10510:80 php:apache

同じように接続してみます。 /get.php?count=9 に GET でリクエストしてみます。

$ telnet localhost 10510
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /get.php?count=9 HTTP/1.0
HTTP/1.1 200 OK
Date: Tue, 17 Oct 2023 11:07:24 GMT
Server: Apache/2.4.57 (Debian)
X-Powered-By: PHP/8.2.11
Vary: Accept-Encoding
Content-Length: 109
Connection: close
Content-Type: text/html; charset=UTF-8

まさかりまさかりまさかりまさかりまさかりまさかりまさかりまさかりまさかり
Connection closed by foreign host.

「まさかり」が9個返ってきましたね!

次は POST で接続してみます。 /post.php にメッセージボディに JSON を渡してリクエストします。

$ telnet localhost 10510
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
POST /post.php HTTP/1.0
Content-Length: 13
Content-Type: application/json

{"count": 9}
HTTP/1.1 200 OK
Date: Tue, 17 Oct 2023 11:09:09 GMT
Server: Apache/2.4.57 (Debian)
X-Powered-By: PHP/8.2.11
Content-Length: 28
Connection: close
Content-Type: text/html; charset=UTF-8

りりりりりりりりり
Connection closed by foreign host.

まさか「り」が9個返ってきましたね!

参考

今回使った PHP ファイルです。

get.php
<?php

$count = $_GET["count"];

$str = "";
for ($i = 0; $i < $count; $i++) {
    $str .= "まさかり";
}

echo $str . PHP_EOL;
post.php
<?php

$json = file_get_contents("php://input");
$data = json_decode($json, true);

$count = $data["count"];

$str = "";
for ($i = 0; $i < $count; $i++) {
    $str .= "り";
}

echo $str . PHP_EOL;

Discussion