この計画の目的は、php_cli_server.c を一気に全面改修することではなく、次の 3 つの将来課題に耐えられる構造へ段階的に変えることです。
-
http_parser依存の緩和と将来のllhttp移行準備 -
TLS 対応のための PHP Stream API 化の準備
-
将来の Polling API 導入を見据えた event loop/backend の分離
現状の関数分類を見ると、イベントループ、request parse callback、response/send 系、SAPI 層が同居しているため、変更の blast radius が大きい状態です。
基本方針は次の 4 つです。
最初の目標は upstream に受け入れられる内部整理です。
外部再利用は副次的成果として扱います。
主眼は file split 自体ではなく、以下の差し替え点を作ることです。
-
parser backend
-
request builder
-
response builder / emitter
-
poll backend
-
transport backend
-
SAPI bridge
最初の PR 群では挙動変更を避け、レビューしやすい分割から始めます。
去年の計画では命名揺れの整理が先頭にありましたが、今年版では命名は主戦場ではなく、責務境界が見えてから追従させます。
最終的な内部構造の目標像は次です。
イベントループ、FD 管理、poller、worker 起動周辺。
現在の php_cli_server_poller_*、php_cli_server_do_event_loop、php_cli_server_send_event などを収容する候補です。
接続単位のライフサイクル管理。
client_ctor/dtor、接続 close、接続状態遷移など。
parser callback の受け皿。
いま php_cli_server_client_read_request_on_* にぶら下がっている逐次イベント処理をここへ隔離する。
完成済み request の表現。
request_ctor/dtor/startup/shutdown、必要なら path/query/header/body の内部表現を持つ。
http_parser / 将来の llhttp backend。
built-in server 本体が parser callback API に直接依存しない構造を目指す。
status line、必須ヘッダー、header 追加、error response などの response builder。
去年の ResponseBuilder 構想をここで内部表現として現実化する。
chunk、buffer、content sender、partial write のような送信パイプライン。
php_cli_server_content_sender_*、php_cli_server_chunk_*、php_cli_server_buffer_* をここへ寄せる。
php_cli_server_ と sapi_cli_server_ の接続面。
去年の「bridge 的な中間層」案はここで生かせます。
ログ、タイミング、TTY 判定、補助ユーティリティ。
レビューで受け入れられる地盤を作ること。
-
関数分類を最新版として更新する
-
callback 群の状態遷移表を作る
-
poll/log/utilityのような比較的独立度の高い部分を別ファイルへ移す -
status_comp、get_last_error、cli_header_value_dtor、destroy_request_infoなどを「暫定 bridge / 保留関数」として棚上げ管理する。これらは去年の計画でも “グラデーション部” として問題意識がありました。
-
Stream API 化
-
llhttp 導入
-
request/response 構造体の全面刷新
-
小さい PR
-
「コード移動主体、挙動変更なし」
-
読みやすい設計メモ
http_parser のイベントモデルを built-in server 本体から切り離すこと。
-
php_cli_server_client_read_request_on_*群をrequest_builder層へ集約 -
message_begin、header_field、header_value、body、message_completeごとに builder state を定義 -
clientが parser の細粒度イベントを直接知らなくても済む形にする -
parser 固有コードを
parser_http_parser.cのような層へ閉じ込める
ここが、http_parser → llhttp 移行準備の本体です。
いきなり llhttp に差し替えるのではなく、まず callback 直結という構造問題を壊す のが先です。
-
request_builder導入 PR -
parser backend を隔離する PR
レスポンス関連の粒度の悪さを改善し、request 側と対称性のある構造にすること。
-
append_http_status_line -
append_essential_headers -
add_response_header -
php_cli_server_send_error_page -
php_cli_server_client_write_response
などを分析し、以下へ分離する。
レスポンスの意味内容を組み立てる層
status, headers, body metadata, close policy を持つ
chunk, buffer, content sender, partial write を扱う層
去年の ResponseBuilder 構想と「ストーリーテラー関数」構想は、このフェーズで採用するのが自然です。
-
response builder 導入
-
sender 分離
-
必要なら高水準 helper 関数の内部整理
raw socket 前提を薄め、PHP Stream API 化のための交換点を作ること。
-
accept/read/write/close を transport 層にまとめる
-
現状は socket transport だけを実装
-
stream transport は別 PR または実験ブランチで準備
-
TLS 対応は transport/backend 差し替えとして語る
この段階でも一気に全面 Streams 化はしない。
まずは transport abstraction を作る ことが目的です。
現在のイベントループから将来の Polling API への道筋を作ること。
-
poller_add/remove/poll/iterを backend インターフェイスとして整理 -
現状 backend を温存
-
将来の Polling API backend を追加可能な形にする
ここで Polling API 実装まで一気に入れなくてよいです。
まずは backend 境界を作る。
upstream が停止した http_parser 依存を減らすこと。
-
parser_http_parserとparser_llhttpを比較可能にする -
request builder 層のテストを使って parser backend の差分を検証
-
挙動差分を局所化してレビューしやすくする
llhttp 導入は、前段の builder 分離なしでは危険です。
このフェーズは必ず後ろに置きます。
実際の優先順位は次です。
-
poll/log/ utility の分離 -
request builder 導入
-
parser backend 隔離
-
response builder / sender 分離
-
transport abstraction
-
llhttp backend
-
Stream transport / TLS
-
Polling API backend
この順番なら、去年の計画にあった response 改善と、今年の parser / TLS / polling 問題を 1 本の線でつなげられます。
poll と log のファイル分割
狙い: no behavior change
request callback 群の棚卸しと request_builder 下地追加
狙い: parser 直結の緩和
http_parser 依存コードの adapter 化
狙い: llhttp 準備
response builder / sender 分離
狙い: response path の明確化
transport abstraction 追加
狙い: TLS 準備
llhttp backend 実験または optional 導入
狙い: parser 更新
この粒度なら、1 回のレビューで抱える論点を減らせます。
upstream に説明するときの主軸は次です。
-
現在の単一ファイルには複数の変更軸が混在している
-
parser backend 置換、TLS 対応、poll backend 差し替えのためには内部境界が必要
-
最初の変更は no behavior change を守る
-
高水準 API 提案ではなく、内部責務の分離である
去年の計画にあった httpserver.h 的な超高水準 API 構想は、今は前面に出さず、将来余地として心に留める程度でよいです。
いま着手するなら、最初の TODO はこれです。
-
関数分類を「移動候補」「保留」「境界関数」に再マークする
-
callback 10 個について、入力・更新対象・一時状態・完成通知を表にする
-
pollとlogの移動対象関数を具体名で決める -
request_builderの最小責務を書く -
ResponseBuilderを今すぐ実装するのではなく、response builder / sender の境界だけ文章化する