Slide 1

Slide 1 text

HTTPリクエストとPHP
 PHPerKaigi petit @福岡 202201
 2022.1.22
 清家史郎
 1


Slide 2

Slide 2 text

自己紹介
 清家 史郎
 @seike460
 - ID
 - GitHub:seike460
 - Twitter:@seike460
 - Work at
 - 株式会社 Fusic (フュージック) 
 技術開発本部/技術開発第一部門 
 - チームリーダー/エバンジェリスト 
 プリンシパルエンジニア
 - Skill
 - PHP/Go/AWS
 - Community
 - Fukuoka.php Organizer 
 - PHP Conference 2018 - 2021 
 - PHPerKaigi 2019 - 2021 
 2


Slide 3

Slide 3 text

Agenda
 3
 1. HTTP メッセージ
 2. HTTP リクエスト
 3. HTTP ヘッダー
 4. PHPとHTTPレスポンス
 5. まとめ


Slide 4

Slide 4 text

01 HTTP メッセージ


Slide 5

Slide 5 text

PHPWebアプリケーションはどうやって動く?
 5
 ブラウザ等のクライアントからHTTPプロトコルを介して
 HTTPメッセージのやり取りを行います。


Slide 6

Slide 6 text

HTTP
 6
 Hypertext Transfer Protocol (HTTP) は HTML などのハイパーメディア文書を 
 転送するためのアプリケーション層プロトコル 
 ウェブブラウザー(クライアント)とウェブサーバー間の通信を目的として設計 
 ※他の用途でも使用されることが有り 
 
 HTTP は旧来のクライアント・サーバーモデルに則っており、クライアントはサーバーに 
 リクエストを送信するためにポートを開き、サーバー側からのレスポンスが返ってくるまで待機。 
 
 HTTP ヘッダーによって、プロトコルの拡張や実験が容易になっており 、新しい機能であっても、
 クライアントとサーバーが新たなヘッダーの意味について単純な合意があれば導入可能。 
 
 HTTP はいわゆるステートレスプロトコルであり、
 サーバーは二つのリクエスト間で何もデータを保持しない。 
 参考:MDN Web Docs「HTTP」: https://developer.mozilla.org/ja/docs/Web/HTTP


Slide 7

Slide 7 text

HTTP
 7
 クライアントとサーバーは、個々のメッセージを交換することによって通信。 
 キャッシュ、フィルタリング、認証、負荷分散等の機能を提供するプロキシを中継することもある。 
 リクエスト…クライアントが送信するメッセージ 
 レスポンス…サーバーが回答として送信するメッセージ 
 参考:MDN Web Docs「HTTP」: https://developer.mozilla.org/ja/docs/Web/HTTP


Slide 8

Slide 8 text

HTTPリクエストとHTTPレスポンス
 8
 ブラウザ等のクライアントからHTTPプロトコルを介して
 HTTPメッセージのやり取りを行います。
 クライアントが送信してサーバーにアクションを起こさせる
 →HTTPリクエスト
 サーバーの回答であるレスポンス
 →HTTPレスポンス


Slide 9

Slide 9 text

HTTP メッセージ
 9
 HTTPリクエストは図の様な決まった形式のテキストを送信することで、
 様々な情報を付与してサーバーに情報を要求して、
 サーバーは要求されたリクエストに応じて処理を変更する事が出来る。


Slide 10

Slide 10 text

02 HTTP リクエスト


Slide 11

Slide 11 text

HTTP のフロー
 11
 1.TCPコネクションを開く(3ウェイ・ハンドシェイク)
 2.HTTP メッセージを送信する(HTTPリクエスト)
 3.サーバーから送信されたレスポンスを読み取る(HTTPレスポンス)
 4.次のリクエストのために、コネクションを閉じるか再使用する
 ※HTTP/1.1


Slide 12

Slide 12 text

curlによるHTTPリクエスト
 12
 $ curl -v --http1.1 https://httpbin.org/get 
 
 * Trying 35.171.190.227:443... 
 * Connected to httpbin.org (35.171.190.227) port 443 (#0) 
 * ~省略~
 * SSL certificate verify ok. 
 > GET /get HTTP/1.1 
 > Host: httpbin.org
 > User-Agent: curl/7.77.0 
 > Accept: */*
 >
 * Mark bundle as not supporting multiuse 
 < HTTP/1.1 200 OK 
 < Date: Sat, 22 Jan 2022 00:45:29 GMT 
 < Content-Type: application/json 
 < ~省略~


Slide 13

Slide 13 text

HTTPリクエストの構成要素
 13
 > GET /get HTTP/1.1 
 ■リクエストライン
 GET … HTTP メソッド。クライアントが実行したい操作を定義する GET や POST等 
 /get … リソースのパス 
 HTTP/1.1 … HTTP プロトコルのバージョン 
 
 > Host: httpbin.org
 > User-Agent: curl/7.77.0 
 > Accept: */*
 ■リクエストヘッダー 
 サーバーに追加の情報を与える任意のHTTPヘッダー 
 >
 ■空行
 ■メッセージボディ
 POST等の場合はリクエスト内にボディが挿入されることがある。 


Slide 14

Slide 14 text

POST リクエスト
 14
 $ curl -v -X POST --http1.1 https://httpbin.org/post 
 * ~省略~
 * SSL certificate verify ok. 
 > POST /post HTTP/1.1 
 > Host: httpbin.org
 > User-Agent: curl/7.77.0 
 > Accept: */*
 >
 * Mark bundle as not supporting multiuse 
 < HTTP/1.1 200 OK 
 < Date: Sat, 22 Jan 2022 01:14:54 GMT 
 < Content-Type: application/json 
 < Content-Length: 318 
 < ~省略~
 


Slide 15

Slide 15 text

POST Bodyの送信
 15
 $ curl -v -H "Content-Type: application/json" -d '{"hoge":"fuga"}' --http1.1 https://httpbin.org/post 
 ~省略~
 * SSL certificate verify ok. 
 > POST /post HTTP/1.1 
 > Host: httpbin.org
 > User-Agent: curl/7.77.0 
 > Accept: */*
 > Content-Type: application/json 
 > Content-Length: 15 
 >
 * Mark bundle as not supporting multiuse 
 < HTTP/1.1 200 OK 
 ~省略~


Slide 16

Slide 16 text

POST Bodyの送信
 16
 $ curl -v -H "Content-Type: application/json" -d '{"hoge":"fuga"}' --http1.1 --trace-ascii - https://httpbin.org/post 
 ~省略~
 0000: POST /post HTTP/1.1 
 0015: Host: httpbin.org 
 0028: User-Agent: curl/7.77.0 
 0041: Accept: */*
 004e: Content-Type: application/json 
 006e: Content-Length: 15 
 0082:
 => Send data, 15 bytes (0xf) 
 0000: {"hoge":"fuga"} 
 == Info: Mark bundle as not supporting multiuse 
 <= Recv header, 17 bytes (0x11) 
 0000: HTTP/1.1 200 OK 
 ~省略~


Slide 17

Slide 17 text

03 HTTP ヘッダー


Slide 18

Slide 18 text

HTTP ヘッダー
 18
 HTTP リクエストやレスポンスでクライアントやサーバーが追加情報を渡す リクエストヘッダー … 読み込むリソースについての情報や、クライアントに関する詳細な情報 レスポンスヘッダー … レスポンスに関する追加情報(場所や提供しているサーバーに関する情報) エンティティヘッダー … リソースの本体に関する情報(MIMEタイプや適用されるエンコード/圧縮方式などについての情報) ペイロードヘッダー … 転送されるデータの表現から独立した情報(コンテンツ長さや転送エンコード方式) 参考:MDN Web Docs「HTTP」: https://developer.mozilla.org/ja/docs/Web/HTTP


Slide 19

Slide 19 text

Google Chrome 開発者ツール
 19


Slide 20

Slide 20 text

httpbin.org/getが返還するJSON
 20
 {
 args: { },
 headers: {
 Accept: "~省略~",
 Accept-Encoding: "gzip, deflate, br",
 Accept-Language: "ja,en-US;q=0.9,en;q=0.8",
 Cache-Control: "max-age=0",
 Host: "httpbin.org",
 Sec-Ch-Ua: "" Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97"",
 Sec-Ch-Ua-Mobile: "?0",
 Sec-Ch-Ua-Platform: ""macOS"",
 Sec-Fetch-Dest: "document",
 Sec-Fetch-Mode: "navigate",
 Sec-Fetch-Site: "none",
 Sec-Fetch-User: "?1",
 Upgrade-Insecure-Requests: "1",
 User-Agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36 ",
 X-Amzn-Trace-Id: "Root=1-61eb64b7-24bc07aa6d8b197a203a12a9"
 },
 origin: "125.56.55.69",
 url: "https://httpbin.org/get"
 }


Slide 21

Slide 21 text

一般的なHTTPリクエストヘッダー
 21
 Accept: "*/*"
 クライアントが理解できるコンテンツタイプを MIME タイプで伝える
 
 Accept-Encoding: "gzip, deflate, br"
 コンテンツのエンコーディング、ふつうは圧縮アルゴリズムのどれをクライアントが理解することができるかを示します
 Apacheのmod_deflate等が利用
 gzip:Lempel-Ziv coding (LZ77) と32ビット CRC を用いた圧縮形式
 deflate:zlib 構造体と deflate 圧縮アルゴリズムを用いた圧縮形式
 br:Brotli アルゴリズムを用いた圧縮形式
 
 Accept-Language: "ja,en-US;q=0.9,en;q=0.8"
 クライアントがどの言語を理解できるか、どの種類のロケールが推奨されるかを示す
 
 Cache-Control: "max-age=0"
 キャッシュをコントロールするヘッダーで、 no-storeをつけることでキャッシュをさせなくしたり、有効期限を設定したりします。


Slide 22

Slide 22 text

拡張HTTPリクエストヘッダー
 22
 Sec-Fetch-Dest: "document",
 Sec-Fetch-Mode: "navigate",
 Sec-Fetch-Site: "none",
 Sec-Fetch-User: "?1",
 フェッチメタデータリクエストヘッダー
 リクエストの発信元のコンテキストに関する追加情報を提供する HTTP リクエストヘッダー
 リクエストがどこから来たのかという追加情報をサーバーに提供し、悪意のあるリクエストを無視できるようになる
 
 Sec-Ch-Ua: "" Not;A Brand";v="99", "Google Chrome";v="97", "Chromium";v="97""
 Sec-Ch-Ua-Mobile: "?0",
 Sec-Ch-Ua-Platform: ""macOS"",
 User-Agent Client Hints
 ユーザーエージェント(UA)クライアントヒントヘッダにより、サーバーはユーザーエージェント(ブラウザ)、
 オペレーティングシステム、デバイスに応じて応答を変化させることができる。
 
 X-Amzn-Trace-Id: "Root=1-61eb64b7-24bc07aa6d8b197a203a12a9"
 AWSが付与するTrace情報
 Application Load Balancerが付与するIDで、リクエストの行方を追うために利用する


Slide 23

Slide 23 text

Sessionが利用するHTTPリクエストヘッダー
 23
 Cookie: "hoge=XxxxxxxxxxxxxxxxxxxxxxxxxxX" 
 
 サーバーが情報処理後、状態を維持するのに必要な情報をサーバーに保存して、セッションIDを発行 
 レスポンスヘッダーのSet-Cookie ヘッダーでセッションIDを送信 
 保存されたCookieからセッションIDをリクエストヘッダーに付与する事で、最初に保存した状態の情報をやり取りする 
 
 詳しくは、PHPerKaigi2021 / PHPで学ぶ Session の基本と応用 / web-app-session-101 @hanhan1978


Slide 24

Slide 24 text

04 HTTPリクエストとPHP


Slide 25

Slide 25 text

HTTPリクエスト情報をPHPで取得する
 25
 $ php -S localhost:8000 
 [Sat Jan 21 23:01:11 2022] PHP 7.4.27 Development Server (http://localhost:8000) started 
 [Sat Jan 21 23:02:53 2022] [::1]:56677 Accepted 
 [Sat Jan 21 23:02:53 2022] [::1]:56677 [200]: GET / 
 [Sat Jan 21 23:02:53 2022] [::1]:56677 Closing 
 
 $ curl -v --http1.1 http://localhost:8000 


Slide 26

Slide 26 text

Laravel public/index.php
 26
 同じ様に$_GETや$_POSTを利用することで 
 HTTPリクエストからの情報をPHPにて取得可能 
 
 一方スーパーグローバル変数をそのまま利用するのは 
 利用できるスコープの観点からもアンチパターン 
 
 では実際はどの様に処理しているのかを 
 Laravelを例に見てみます。 


Slide 27

Slide 27 text

Laravel と HTTPリクエスト
 27


Slide 28

Slide 28 text

Laravel と HTTPリクエスト
 28


Slide 29

Slide 29 text

Laravel と HTTPリクエスト
 29


Slide 30

Slide 30 text

Laravel と HTTPリクエスト
 30


Slide 31

Slide 31 text

Laravel と HTTPリクエスト
 31


Slide 32

Slide 32 text

HTTPリクエストの行方 
 〜Laravelがレスポンスを返すまで〜
 32


Slide 33

Slide 33 text

05 まとめ


Slide 34

Slide 34 text

まとめ
 Point 3
 HTTPリクエストに様々な情報を載せる事でPHPは動作を決める事が出来る 
 34
 PHPは一般的にHTTPメッセージであるHTTPリクエストを契機にHTTPレスポンスを構築する
 Point 1
 
 HTTPリクエストはリクエストライン、リクエストヘッダー、メッセージボディで構成される
 Point 2


Slide 35

Slide 35 text

ご清聴いただきありがとうございました
 Thank You We are Hiring !
 https://recruit.fusic.co.jp/