RFC 7230: Hypertext Transfer Protocol (HTTP/1.1)
まずはGETリクエスト(HTTPリクエスト)とは何なのか、RFCを確認します。
https://www.rfc-editor.org/rfc/rfc7230
https://triple-underscore.github.io/RFC7230-ja.html
HTTP request
は以下のような構成です。
request-line
header fields
empty line
payload body
以下のような表記もなされていました。
HTTP-message = start-line
*( header-field CRLF )
CRLF
[ message-body ]
以下のサイトでは次のように翻訳しているようです。
https://wa3.i-3-i.info/word1845.html
HTTPリクエストライン(リクエストライン)
HTTPリクエストヘッダ(ヘッダ)
空行
HTTPリクエストメッセージボディ(メッセージボディ)
「ネットワークはなぜつながるのか」では次のように翻訳されていました。
リクエスト・ライン
メッセージ・ヘッダー
メッセージ・ボディ
表記は色々あるようですね。
curlコマンドのHTTPリクエストを確認する
curl --http1.1 -v https://www.google.com
>
で始まっている行を抜粋すると、たしかにRFCに従っていることが確認できました。
> GET / HTTP/1.1
> Host: www.google.com
> user-agent: curl/7.79.1
> accept: */*
>
この例ではGETリクエストなのでpayload body
は存在しません。ただし、empty line
は含まれています。
socketを利用してGETリクエストを送る
では以下のHTTP request
を実際にWebサーバに送信してみます。先程のcurlコマンドのHTTPリクエストをコピペして、txtファイルを作成しておきます。
curl_request.txt
GET / HTTP/1.1
Host: www.google.com
user-agent: curl/7.79.1
accept: */*
以下のPythonスクリプトを作成して実行します。
client.py
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('www.google.com', 80))
with open('curl_request.txt', 'rb') as f:
client.send(f.read())
response = client.recv(4096)
client.close()
print(response.decode())
コードの一部は以下を参考にさせていただきました。
HTTP/1.1 200 OK
(以下略)
正常にリクエストを送信できました。
補足
- GETリクエストであっても
empty line
が必要です。試しに削除してリクエストしてみましょう。 - curlでわざわざ
--http1.1
オプションを付けていますが、私の環境ではつけなかった場合にHTTP/2
でのリクエストになりました。また、理由を深掘っていませんが、HTTP/2
ではwww.google.com
から200 OK
を受信できなかったために天下り的にHTTP/1.1
で進めています。