さる技術書典で書く原稿のためにHTTPについて調べていたら、こんな記述を見つけた。

HTTP/0.9 は、1991年以来使われている HTTP の最初の版です。 極めて単純ですが、あまりに低機能なので、現在ではほとんど使われなくなっています。 それでも HTTP プロトコルの一部として依然として広く実装されています。
HTTP/0.9 - SuikaWiki (強調引用者)

本当だろうか。

HTTP/0.9といえば、HTTP/1.0やHTTP/1.1に上書きされて悠久の昔に忘れ去られた、古のプロトコルであるという認識である。NetScapeもバージョン2.0からHTTP/1.1を実装している

HTTP/0.9とは

  • GETリクエストしか存在しない
  • HTTPヘッダなんてない
  • HTTPステータスコードなんてない
  • 応答は原則HTMLのみ

つまり、HTTP/0.9を正しく実装している場合、リクエストとレスポンスは以下のようになる。

$ echo -e "GET /\r\n" | nc hogehoge.hoge 80
<html><body><h1>Yatta!</h1></body></html>

これ以上ないほどシンプル。

調査方法

Alexa Top Sites の日本ランキングを参照し、国内トップ25のウェブサイトを順番に検証した。

深いことは考えずにドメイン名に対して手元でecho -e "GET /\r\n" | nc hogehoge.hoge 80を実行して、HTTPヘッダなしのHTMLが帰ってくればOK。それ以外ならアウトとした。

調査結果

#1: :no_good: google.co.jp

$ echo -e "GET /\r\n" | nc google.co.jp 80
HTTP/1.0 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.jp/?gfe_rd=cr&ei=Kf9oV5byD8_d8AeG1oH4Cg
Content-Length: 261
Date: Tue, 21 Jun 2016 08:47:37 GMT

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.jp/?gfe_rd=cr&amp;ei=Kf9oV5byD8_d8AeG1oH4Cg">here</A>.
</BODY></HTML>

筆頭はやはりGoogle様。ちゃんとリクエストとして認識されたが、どうやらHTTP/1.0と判定されてヘッダー付きのレスポンスが返ってきてしまった。Googleさえ実装していないということで先行きが不安に。

#2: :no_good: google.com

$ echo -e "GET /\r\n" | nc google.com 80
HTTP/1.0 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.jp/?gfe_rd=cr&ei=EANpV8eAKtPd8AeFq7jQDA
Content-Length: 261
Date: Tue, 21 Jun 2016 09:04:16 GMT

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.jp/?gfe_rd=cr&amp;ei=EANpV8eAKtPd8AeFq7jQDA">here</A>.
</BODY></HTML>

google.co.jpに同じ。

#3: :no_good: youtube.com

$ echo -e "GET /\r\n" | nc youtube.com 80
HTTP/1.0 302 Found
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Location: http://www.google.co.jp/?gfe_rd=cr&ei=vgBpV4LwMMvD8AfW8rvQBQ
Content-Length: 261
Date: Tue, 21 Jun 2016 08:54:22 GMT

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.co.jp/?gfe_rd=cr&amp;ei=vgBpV4LwMMvD8AfW8rvQBQ">here</A>.
</BODY></HTML>

#1から#3をGoogleが独占している。YouTubeも今となっては完全にGoogleのインフラで動いているようで、Googleに飛ばされる結果に。まあ、Hostヘッダすら存在しないので仕方ない。

#4: :no_good: yahoo.co.jp

$ echo -e "GET /\r\n" | nc yahoo.co.jp 80
(空のレスポンス)

へんじがない。ただのしかばねのようだ。

#5: :ok_woman: amazon.co.jp

$ echo -e "GET /\r\n" | nc amazon.co.jp 80 | head
<!DOCTYPE html>
<!--[if lt IE 7]> <html lang="jp" class="a-no-js a-lt-ie9 a-lt-ie8 a-lt-ie7"> <![endif]-->
<!--[if IE 7]>    <html lang="jp" class="a-no-js a-lt-ie9 a-lt-ie8"> <![endif]-->
<!--[if IE 8]>    <html lang="jp" class="a-no-js a-lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="a-no-js" lang="jp"><!--<![endif]--><head>
<meta http-equiv="content-type" content="text/html; charset=Shift_JIS">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title dir="ltr">Amazon CAPTCHA</title>

ようやくHTTP/0.9対応サーバーに出会えた。BOT避けのCAPTCHA認証ページが表示される。

HTMLの中身を読んでみると、

申し訳ありませんが、お客様がロボットでないことを確認させていただく必要があります。最良のかたちでアクセスしていただくために、お使いのブラウザがクッキーを受け入れていることをご確認ください。

と書いてあるが、HTTP/0.9にCookieなんて概念は存在しない。大丈夫か。

#6: :no_good: facebook.com

$ echo -e "GET /\r\n" | nc facebook.com 80
HTTP/1.1 301 Moved Permanently
Location: http://www.facebook.com/
Vary: Accept-Encoding
Content-Type: text/html
X-FB-Debug: vkUE+XMR6cNr6Fx86bFOM2WHiRjA/tQ9BOY/JkUAE/nz8QXU6aJLWpzu/3GqqNhKfCO9+UzWAMAHbobjQ7bVEg==
Date: Tue, 21 Jun 2016 09:18:35 GMT
Connection: close
Content-Length: 0

#7: :no_good: twitter.com

$ echo -e "GET /\r\n" | nc twitter.com 80
HTTP/1.0 400 Bad Request
content-length: 0
date: Tue, 21 Jun 2016 09:12:34 GMT
server: tsa_a
x-connection-hash: a7567fd4ae6dd605ac788fd4ee7aaf47

Twitterには怒られてしまった。そりゃそうだ。

#8: :no_good: nicovideo.jp

$ echo -e "GET /\r\n" | nc nicovideo.jp 80
(空のレスポンス)

へんじが(ry

#9: :ok_woman: rakuten.co.jp

$ echo -e "GET /\r\n" | nc rakuten.co.jp 80
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://www.rakuten.co.jp/">here</a>.</p>
</body></html>

楽天もHTTP/0.9を実装しているようだ。ちなみに指示に従ってwww.rakuten.co.jpにアクセスすると、

$ echo -e "GET /\r\n" | nc www.rakuten.co.jp 80
HTTP/1.0 400 Bad Request
Server: AkamaiGHost
Mime-Version: 1.0
Content-Type: text/html
Content-Length: 216
Expires: Tue, 21 Jun 2016 09:15:06 GMT
Date: Tue, 21 Jun 2016 09:15:06 GMT
Connection: close

<HTML><HEAD>
<TITLE>Bad Request</TITLE>
</HEAD><BODY>
<H1>Bad Request</H1>
Your browser sent a request that this server could not understand.<P>
Reference&#32;&#35;7&#46;77fa3d17&#46;1466500506&#46;0
</BODY>
</HTML>

やっぱりダメだったよ……。

#10: :no_good: wikipedia.org

$ echo -e "GET /\r\n" | nc wikipedia.org 80 | head
HTTP/1.1 200 OK
Server: mw1237.eqiad.wmnet
X-Powered-By: HHVM/3.3.0-static
Last-Modified: Tue, 02 Feb 2016 14:25:41 GMT
ETag: "3d2-52aca46b79fd9"
Backend-Timing: D=331 t=1466450885836078
Content-Type: text/html
X-Varnish: 3085455895 3075460739, 1992728546 1956129338, 1936721017 1901985864, 2750998498 2702150686
Via: 1.1 varnish, 1.1 varnish, 1.1 varnish, 1.1 varnish
Date: Tue, 21 Jun 2016 09:21:42 GMT

「OK」じゃないが。

#11: :no_good: fc2.com

$ echo -e "GET /\r\n" | nc fc2.com 80
HTTP/1.1 503 Service Unavailable.
Content-length:0

HTTP/1.1と認識されたようだ。少なくともHTTPリクエストとして認識したなら101か400あたりを返すべきだと思うのだが、ステータスコードは503でいいのだろうか。

ちなみにHTTP/1.1でもHostヘッダを付けないと同じ結果が返ってくる。

#12: :no_good: t.co

$ echo -e "GET /\r\n" | nc t.co 80
HTTP/1.0 400 Bad Request
content-length: 0
date: Tue, 21 Jun 2016 09:29:47 GMT
server: tsa_a
x-connection-hash: 8cdb0c1644972b66bdf6392ae9901abf

twitter.comとほぼ同じ結果。

#13: :no_good: baidu.com

$ echo -e "GET /\r\n" | nc baidu.com 80

へんじがない。

#14: :ok_woman: kakaku.com

$ echo -e "GET /\r\n" | nc kakaku.com 80 | head
<!doctype html>
<!--[if lte IE 8]><html class="is-ie8" lang="ja" prefix="og: http://ogp.me/ns# fb: http://www.facebook.com/2008/fbml"><![endif]-->
<!--[if IE 9]><html class="is-ie9" lang="ja" prefix="og: http://ogp.me/ns# fb: http://www.facebook.com/2008/fbml"><![endif]-->
<!--[if gt IE 9]><!--><html lang="ja" prefix="og: http://ogp.me/ns# fb: http://www.facebook.com/2008/fbml"><!--<![endif]-->
<head>
<!--[if IE]>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<![endif]-->
<meta charset="shift_jis">

最初の10行だけでこれ以上ないつらみを感じられるHTMLが降ってくる。

#15: :ok_woman: ameblo.jp

$ echo -e "GET /\r\n" | nc ameblo.jp 80 | head
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
<head>
<meta http-equiv="content-language" content="ja" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta http-equiv="content-style-type" content="text/css" />
<meta http-equiv="content-script-type" content="text/javascript" />
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta http-equiv="Pragma" content="no-cache" />

レスポンスのHTMLの<title>は「403エラー|Ameba(アメーバブログ)」となっている。HTTP/0.9に足りないものをHTMLで補う模範的なHTTP/0.9実装といえる(?)。

#16: :ok_woman: livedoor.com

$ echo -e "GET /\r\n" | nc livedoor.com 80
<html>
<body>
<h1>It lives!</h1>
</body>
</html>

元気そうで何より。

#17: :ok_woman: amazon.com

$ echo -e "GET /\r\n" | nc amazon.com 80
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>Server</center>
</body>
</html>

amazon.co.jpと応答が異なる。しかし Moved Permanently と言われるだけでどこにMovedなのか一向にわからない。

#18: :no_good: qq.com

$ echo -e "GET /\r\n" | nc qq.com 80

へんじがない。

#19: :ok_woman: livedoor.jp

$ echo -e "GET /\r\n" | nc livedoor.jp 80
<html>
<body>
<h1>It lives!</h1>
</body>
</html>

ひょっとしてこのlivesは、livedoorと掛かっているのだろうか。

#20: :no_good: instagram.com

$ echo -e "GET /\r\n" | nc instagram.com 80

instagramは意外にこの順位。HTTP/0.9はインスタ映えしないようだ。

#21: :ok_woman: tmall.com

$ echo -e "GET /\r\n" | nc tmall.com 80 | head
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head><title>501 Not Implemented</title></head>
<body bgcolor="white">
<h1>501 Not Implemented</h1>
<p>The requested method to the URL not supported. Sorry for the inconvenience.<br/>
Please report this message and include the following information to us.<br/>
Thank you very much!</p>
<table>
<tr>

初めて Not implemented と出力された。HTTP/0.9意識が最も高いのはこれかもしれない。

#22: :ok_woman: yahoo.com

$ echo -e "GET /\r\n" | nc yahoo.com 80 | head
<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <title>Yahoo</title>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimal-ui">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <style>
      html {

#23: :ok_woman: live.com

$ echo -e "GET /\r\n" | nc live.com 80
<h2>Our services aren't available right now</h2><p>We're working to restore all services as soon as possible. Please check back soon.</p>Ref A: 86EC138BB668446ABEBC3997CC84699D Ref B: OSA02EDGE0415 Ref C: 2017-12-09T05:19:34Z

これをHTTP/0.9対応と言っていいのか微妙だが、一応認識はされてそうなので:ok_woman:にした。

#24: :ok_woman: taobao.com

$ echo -e "GET /\r\n" | nc taobao.com 80 | head
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html>
<head><title>501 Not Implemented</title></head>
<body bgcolor="white">
<h1>501 Not Implemented</h1>
<p>The requested method to the URL not supported. Sorry for the inconvenience.<br/>
Please report this message and include the following information to us.<br/>
Thank you very much!</p>
<table>
<tr>

タオバオはT-mallの運営母体なので、同じ結果が帰ってくる。

#25: :no_good: reddit.com

$ echo -e "GET /\r\n" | nc reddit.com 80 | head
HTTP/1.1 500 Domain Not Found
Server: Varnish
Retry-After: 0
content-type: text/html
Cache-Control: private, no-cache
connection: keep-alive
X-Served-By: cache-itm18820-ITM
Content-Length: 221
Accept-Ranges: bytes
Date: Sat, 09 Dec 2017 05:24:13 GMT

500は Internal Server Error のはずだが、これはHTTP/1.1の仕様として正しいのだろうか。

まとめ

HTTP/0.9対応サイト (暫定)

以上のように、日本のトップドメイン25個のうち、11個のウェブサイトがHTTP/0.9を実装していることがわかった。冒頭の記事の記述通り、依然としてHTTP/0.9は広く実装されているが、この記事をきっかけにHTTP/0.9がより浸透し、Netscape 1.0 ユーザーが快適にウェブブラウジングできるよう、日本と言わず世界中でHTTP/0.9の実装率が向上することを心から願っている。

明日は @catatsuy がJavaScriptの話をします。お楽しみに。

おまけ

おそらく何かの間違いで我らがpixivがトップ25に入っていなかったので、ついでに検証してみる。

$ echo -e "GET /\r\n" | nc pixiv.net 80
<html>
<head><title>403 Forbidden</title></head>
<body bgcolor="white">
<center><h1>403 Forbidden</h1></center>
<hr><center>nginx</center>
</body>
</html>

ヘッダーが足りないので怒られるが、応答はHTTP/0.9として正常なので:ok_woman:である。