こんぶにのブログ

エンジニアという職業を通して学んだことを発信するブログです。

【3年目でやっと分かった】PHPとApacheを使って色々やってみて、HTTPリクエストを少し理解できた

はじめに

前回の続きになります。
脱・伸び悩みWebエンジニアシリーズとなります。

konbuni.net

また、以下の記事でインストールしたApacheを本格的に使っていきます。

konbuni.net

HTTPとは?

超簡単に言うと、サーバーにあるファイルを操作するときに使う通信の手順。
(よくプロトコルとか規約とか言われるけど、自分はその説明だと正直全く分からんかった…。)
あるサーバー(サイト)にあるこのファイル(ページ)が見たい!!
そんなときはこのHTTPの定められた手順に乗っ取り、そのルールを守って、何かを作成したり送ったりする必要がある。
その一つがHTTPの中のGETメソッド(サーバーにファイルを見たい!という要望を送る)だったり、POSTメソッド(これから勉強予定)だったり。
例えば、ブラウザでURLを入力するときは最初にhttp~と入力しますよね。
これは、「あるサイトのページが見たいから、この通信はHTTPの全ルールに則って行うよ!!!」とブラウザに教え込んでいる。 すると、ブラウザ君も
お!httpね!じゃあそのルールに則ったリクエストの送り方するわ!! みたいになる。
そしてヘッダーとか作ってくれたり、レスポンスを返してくれたりする。
結果、ブラウザ上でこの世のどこかのサーバ(サイト)のファイル(ページ)が見れる。
そういうのを全部含めて規約とかプロトコルと呼んでいるんだと思うが、
こういう所がエンジニアという仕事の難易度を上げている気がする。
自分が具体的にどういうことなのかを教えてもらわないと、概念だけでは全くイメージしづらい人間だからなのかもしれないけど。

HTTPリクエストを知る

じゃあ実際にHTTPを使って、どんなことをやり取りしているのか?
HTTPの核心に迫ってみる。(迫るだけ)

Apache起動

まずはApacheを起動する。
今回はwindowsで行うので、コマンドは

httpd

のみ。
これで自分のPCのport80番でいつでも何かを待ち受けている状態が完成。
なので、何か自分のPC上のファイルを見たいときは、宛先を自分のPC(localhost)の80番に対して行う必要がある。
今は手軽にリクエスト送るのも、それを返すのも全部自分のPCでやっているけど、
本当だったらApacheを動かすサーバーと、そこにリクエストを送るクライアントは別のサーバーが行うという認識が大事。
仕事など実務では、この指定する宛先サーバーは変わってくるはずだ。

リクエストをphpで送信

前回作ったTcpClient.phpを起動。
ソース的にはこんな感じ。

<?php
error_reporting(E_ALL);

// 宛先のport
// $service_port = '8001';
$service_port = '80';
$address = gethostbyname('localhost');

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_connect($socket, $address, $service_port);

$fileName = 'text/client_send.txt';
$sendFile = fopen($fileName, 'rb');
$content = fread($sendFile, filesize($fileName));

echo "送信中・・・";
socket_write($socket, $content);

echo "OK.\n";

echo $socketRead;
$socketRead = socket_read($socket, 2048);
$fileName = 'text/client_recv.txt';
$recvFile = fopen($fileName, 'w');

fwrite($recvFile, $socketRead);
echo "送られてきたソケット↓:\n\n";
echo $socketRead;

echo "ソケットを閉じます...";
socket_close($socket);
echo "OK.\n\n";

?>

変更点は宛先portを80番に変更。
前回はサーバー側と見立てたTcpServer.phpにて、port:8001で通信を待ち受けた。
なので宛先も8001だったが、今回は相手がApacheなのでport:80に。
何故80なのかというのは、全ての人間共通のものと決められているから。
80じゃなくても全然できるけど、共通認識として80というのがあったほうが色々スムーズに行くよね、ってだけ。

httpリクエストヘッダを作成

ここまで来たら、次は何を送るか。
というか、何が欲しいか。
欲しいものとしてはApacheを起動したときに以下のURLを入力すると得られる画面(html)だ。

http://localhost/index.html

成功してるとこんな画面が出るはず。

It works!

http://localhost:80/index.html
としても行ける。
80が当たり前すぎて省略出来てしまう世界。
ともかくIt Worksのこれって、Apacheが動いているサーバの80番にアクセスしたら返ってきたhtmlファイルであることが分かる。
なので、この画面ファイルを頂戴よ~!というのをリクエストしていく。
それがHTTPリクエストヘッダー。
前回の記事のハンズオンでTcpServer.phpを動かしていると得られるものだ。
サーバ上のファイルが欲しいなら、HTTPのルールに則って、HTTP流のお願いをしなければならない。
ということでこれの出番だ。
前回のTcpServer.phpを動かして、ブラウザからhttp://localhost:8001/index.htmlとすると、
ブラウザが「お!HTTPで通信だね!じゃあヘッダーは作って宛先のサーバーに送っておくね!!」と勝手にHTTPヘッダーを作ってくれて、
挙句の果てに、勝手にソケット通信まで確立してくれて、さらにリクエストヘッダーをport8001で動くサーバーに送ってくれた。
おかげで、server_recv.txtにそれが書き込まれていたのだ。
届いた手紙は翻訳するとこんな内容だった。

GET /index.html HTTP/1.1 ##GETでindex.htmlを頂戴~というお願い
Host: localhost:8001##宛名
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7  
##空の行が最後にある。これで終わりだよ~と示すために大事なもの。  

ほとんどの部分は送った人の情報だったりなのでカット。
特に大事なのがコメント部分。
今回はこれを自らの意志で、リクエストはまだかと待っているApache起動中サーバ(Webサーバ)に送ってみる。

client_send.txtにリクエストヘッダ記述

上記ヘッダの宛名のport番号だけを80に変えて、client_send.txtに記述。
これでこの内容を80番との間で確立されたソケットに書き込んでくれます(要は送信)。

実行

さて、以下をコマンドプロンプトで実行してみる。

php TcpClient.php

するとclient_recv.txtというファイルに以下のような文章が記述されているはず。

HTTP/1.1 200 OK ##成功したよ
Date: Wed, 08 Nov 2023 14:33:29 GMT
Server: Apache/2.4.58 (Win64)
Last-Modified: Wed, 08 Nov 2023 14:10:03 GMT
ETag: "d5-609a4a4b899e4"
Accept-Ranges: bytes
Content-Length: 213
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html ##この形式だよ
##↓ファイルの中身
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
<body>
    <h1>It works!</h1>
</body>

</html>

client_recvはサーバからソケットに書き込まれた情報が記述される場所。
つまり、さっきのリクエストヘッダーをApacheの待ち受ける80に送ったら、これを返してくれたということ。
良く見ると、It works!の文字があるhtmlが!!!
これでApache起動→ブラウザでurl入力→例のhtmlが返ってくる
というのを再現できた。
この返ってきたものをレスポンスと言う。
今回はレスポンスを文字として受け取ったのでここで止まっているが、
これをブラウザで受け取れば、例の画面が表示されるということだ。
普段ブラウザは我々の見えないところで色々やってくれているということだろう。

終わり

少し長くなってしまったので今回はここまで。
力尽きてしまった。
次は画像のレスポンスについてやっていこうとおもう。

最後までご覧いただきありがとうございました!!