15
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

手打ち HTTP でコシのあるネット生活

Posted at

HTTP リクエストを送ってみる

みなさんが毎日使っている、HTTP こと、HyperText Transfer Protocol1
普段は、生の HTTP リクエストを意識することはあまりありませんが、中身はプレーンテキストなので、手打ちでも通信をすることができます。

この記事では、手打ちで HTTP による通信をやってみることで、
普段ブラウザや curl がどんな仕事をしているか、思いを馳せてみましょう。

「手打ち」という響きには、うどんとか蕎麦みたいなプレミア感が出て良いです。
きっとあなたにとって特別な HTTP リクエストになるはずです。

今回は簡単な HTTP/1.1 で通信をします。

Telnet クライアントを使えるようにする

HTTP/1.1 は TCP 上で取り交わしますので、まず TCP コネクションを張らなくてはいけません。
この用途で、telnet という CLI プログラムを使います。

Windows の場合は、こちらの手順 で内蔵の telnet クライアントを有効化してください。
MacOS の場合は、Homebrew でインストールできるようです。

brew install telnet

相手方の IP アドレスを調べる

本当は telnet が自動でやってくれるのですが、ここではあえて相手方の IP アドレスを指定して通信します。

相手は HTTP/1.1 に返事してくれる場所ならどこでもいいです。
例えば Google にしてみましょう2。IPv4 のアドレスを調べます。

nslookup google.com
Name: google.com
Address: 142.250.207.110

TCP コネクションを張る

ここからは、TCP コネクションのタイムアウトがあるので、手早く行う必要があります。

キーボードのタイピングに自信がない人や、タイムアウトの短いサーバーにアクセスするときは、あらかじめ次の見出しまで読んで、
リクエスト内容をメモ帳で下書きし、クリップボードに入れておくと、安定してリクエストできるでしょう。

次のコマンドで、google.com がいるサーバーの 80番ポートに、TCP で接続します。
80番はご存知の通り、HTTP の Well-Known port です。

telnet 142.250.207.110 80

HTTP リクエストを送る

次の内容が、送る HTTP リクエストの内容です。簡単ですね。
google.com というホストに対して、/ の内容を GET でリクエストします。

GET / HTTP/1.1
Host: google.com

TCP がつながったら、この内容を素早く打ち込みます。
下書きした人は端末上でペースト操作をします(Ctrl+Shift+V など)。
telnet クライアントによっては、打った内容が画面に表示されないかもしれませんが
気にせず打ち込みます。

最後の改行も忘れず送信してください。
改行を送信すると、すぐに向こうのサーバーから返事があるはずです。

Google の場合はこんな返事でした(レスポンスの HTML は整形しています)。

HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Cross-Origin-Opener-Policy-Report-Only: same-origin-allow-popups; report-to="gws"
Report-To: {"group":"gws","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/gws/other"}]}
Date: Tue, 29 Nov 2022 13:12:14 GMT
Expires: Thu, 29 Dec 2022 13:12:14 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN

<HTML>
  <HEAD>
    <meta http-equiv="content-type" content="text/html;charset=utf-8">
    <TITLE>301 Moved</TITLE>
  </HEAD>
  <BODY>
    <H1>301 Moved</H1>
    The document has moved <A HREF="http://www.google.com/">here</A>.
  </BODY>
</HTML>

長いレスポンスですが、見るべきは最初の2行です。つまり、
「君がアクセスしようとした http://google.com/ は、https://www.google.com/ に移動したから、そっちを見に行ってくれ」
ということです。

HTTP クライアントであるあなたはこれを解釈して、次は https://www.google.com/GET するような HTTP リクエストを作ることになります。

このレスポンスに HTML が入っているのは Google の親切なところです。
仮にブラウザがリダイレクトを追いかけなかったとしても、ユーザーが手動で正しい URL に移動できるようにリンクを返してあげているのですね。

これで、あなたは一番簡単な HTTP リクエストを自分で発行できたことになります3

解説

送ったリクエストと帰ってきたレスポンスを詳しく見てみましょう。

リクエスト

HTTP リクエスト

GET / HTTP/1.1

「HTTP/1.1 を使って、あなたのサーバーの /GET します」という意です。

リクエストが POST メソッドなら、最初が POST になりますし、
リクエスト先が /path/to/index.html なら2番目のフィールドが /path/to/index.html になります。

ヘッダ

Host: google.com

2行目からは HTTP ヘッダを入れる場所になります。ここでは Host ヘッダを指定しました。

今回アクセスした IP アドレスの 142.250.207.110 には、複数のホストがいる可能性があります。
現に、kix06s11-in-f14.1e100.net という名前のホストも、同じ IP アドレスに解決されます。

このときにアクセスしたいサーバが google.com であることを指定するのが、Host ヘッダです。
これがないと、サーバはリクエストが自分に来ているかどうか判断できません。

HTTP ヘッダには他にもいろいろなものがあります。
プレーンテキストで返事してほしいなら、

Accept: text/plain

日本語で返事してほしいなら、

Accept-Language: ja-JP

自分が HTTP リクエストを手入力していることを伝えたいなら(伝わるかどうかはわかりませんが)、

User-Agent: handwriting

などなど、続けて入力することができます。

リクエストの終了

(空行)

次の空行は、リクエストが終わったことを伝えるためのものです。
サーバーは、多少キーボード入力が遅くても、この空行が来るまではリクエストが終わらないと思って待っていてくれます。

逆に空行を入れないと返事が返ってきません。そういうプロトコルです。

レスポンス

HTTP レスポンス

HTTP/1.1 301 Moved Permanently

レスポンスステータスコード 301 のレスポンスです。
これは、アクセスしようとしたコンテンツがそこにはなく、永続的に移動したことを示します。

ヘッダ

Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8

Location ヘッダはコンテンツの移動先を、Content-Type ヘッダはこの下に続くコンテンツが UTF-8 の HTML であることを示します。
そのほかのヘッダは割愛です。

ボディ

ヘッダから1行空けて、HTML 本文が返ってきています。
もちろん、Content-Type が HTML でない場合には、それに応じて違う内容の本文が返ってきます。

HTTPS でリクエストするには

先ほどのレスポンスで、我々は https://www.google.com/ にアクセスしなければならないことがわかりました。
ところが、telnet では SSL/TLS の通信はできないので、HTTPS は通信できません。

この用途では openssl が使えます。

MacOS ならデフォルトで入っているはず。
Windows のかたは ダウンロード してください。

方法は、上記で telnet コマンドで接続するところを、次のように書き換えるだけです。

openssl s_client -quiet -connect www.google.com:443 -crlf

コネクションができさえすれば、あとは同じです4

GET / HTTP/1.1
Host: www.google.com

今度は、大きなレスポンスが返ってきました。

HTTP/1.1 200 OK
Date: Tue, 29 Nov 2022 13:56:47 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=ISO-8859-1
Cross-Origin-Opener-Policy-Report-Only: same-origin-allow-popups; report-to="gws"
Report-To: {"group":"gws","max_age":2592000,"endpoints":[{"url":"https://csp.withgoogle.com/csp/report-to/gws/other"}]}
P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info."
Server: gws
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN
Set-Cookie: 1P_JAR=2022-11-29-13; expires=Thu, 29-Dec-2022 13:56:47 GMT; path=/; domain=.google.com; Secure
Set-Cookie: AEC=AakniGMbUGYXxfVFLLcGURQEFTPychfxs9chpKcj0PQK0Hj3b5w7uNIZAw; expires=Sun, 28-May-2023 13:56:47 GMT; path=/; domain=.google.com; Secure; HttpOnly; SameSite=lax
(略)

5a4d
<!doctype html>
<html itemscope="" itemtype="http://schema.org/WebPage" lang="ja">
(略)

きちんとレスポンスコード 200 が返ってきていることがわかります。
しかも、HTML の言語は日本語になっていますね。
このレスポンス全体は、ぜひ自分の目で確かめてみてください。

で、こんなこといつ使うの?

本記事で取り上げた HTTP リクエストを自力で組み立てるというテクニックは、拙作 Twitter for PC-G850 で、Twitter API と通信する時に使っています。
該当部分のソースは このへんこのへん にあります。よかったらこちらもご覧ください。

次は 12/4 リュース04 さんの「ゲーム制作初心者の自分語り」です。

  1. 日本語訳が「ハイパーテキスト転送プロトコル」なので Haipa-Tekisuto Tensou Purotokoru と覚える方法があるとかないとか。

  2. TCPコネクションのタイムアウトが長いので、キーボードから手でリクエストを打ち込めるのです。他のサービスでいいところがあったら教えてください。

  3. 推しバンドのライブで HTTP によるコール&レスポンスを要求されても大丈夫でしょう。

  4. HTTPS が HTTP over SSL であり、SSL 通信とレイヤーがしっかり分離されている恩恵です。

15
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?