Skip to content

Instantly share code, notes, and snippets.

@masakielastic
Last active March 21, 2026 11:18
Show Gist options
  • Select an option

  • Save masakielastic/59ac23f5c3130ef0a2093b7acd9cc28b to your computer and use it in GitHub Desktop.

Select an option

Save masakielastic/59ac23f5c3130ef0a2093b7acd9cc28b to your computer and use it in GitHub Desktop.
PHP ビルトインサーバー改善案

2026年版 新計画

PHP Built-in Server (sapi/cli/php_cli_server.c) 再設計計画

0. この計画の目的

この計画の目的は、php_cli_server.c を一気に全面改修することではなく、次の 3 つの将来課題に耐えられる構造へ段階的に変えることです。

  1. http_parser 依存の緩和と将来の llhttp 移行準備

  2. TLS 対応のための PHP Stream API 化の準備

  3. 将来の Polling API 導入を見据えた event loop/backend の分離

現状の関数分類を見ると、イベントループ、request parse callback、response/send 系、SAPI 層が同居しているため、変更の blast radius が大きい状態です。


1. 基本方針

基本方針は次の 4 つです。

1-1. 最初から「独立ライブラリ化」は目標にしない

最初の目標は upstream に受け入れられる内部整理です。
外部再利用は副次的成果として扱います。

1-2. 「きれいにする」ではなく「差し替え点を作る」

主眼は file split 自体ではなく、以下の差し替え点を作ることです。

  • parser backend

  • request builder

  • response builder / emitter

  • poll backend

  • transport backend

  • SAPI bridge

1-3. no behavior change を最優先する段階を設ける

最初の PR 群では挙動変更を避け、レビューしやすい分割から始めます。

1-4. 命名整理は境界設計のあとにやる

去年の計画では命名揺れの整理が先頭にありましたが、今年版では命名は主戦場ではなく、責務境界が見えてから追従させます。


2. 新しい構造の目標像

最終的な内部構造の目標像は次です。

A. php_cli_server_poll.*

イベントループ、FD 管理、poller、worker 起動周辺。
現在の php_cli_server_poller_*php_cli_server_do_event_loopphp_cli_server_send_event などを収容する候補です。

B. php_cli_server_client.*

接続単位のライフサイクル管理。
client_ctor/dtor、接続 close、接続状態遷移など。

C. php_cli_server_request_builder.*

parser callback の受け皿。
いま php_cli_server_client_read_request_on_* にぶら下がっている逐次イベント処理をここへ隔離する。

D. php_cli_server_request.*

完成済み request の表現。
request_ctor/dtor/startup/shutdown、必要なら path/query/header/body の内部表現を持つ。

E. php_cli_server_parser_*.*

http_parser / 将来の llhttp backend。
built-in server 本体が parser callback API に直接依存しない構造を目指す。

F. php_cli_server_response.*

status line、必須ヘッダー、header 追加、error response などの response builder。
去年の ResponseBuilder 構想をここで内部表現として現実化する。

G. php_cli_server_sender.*

chunk、buffer、content sender、partial write のような送信パイプライン。
php_cli_server_content_sender_*php_cli_server_chunk_*php_cli_server_buffer_* をここへ寄せる。

H. php_cli_server_sapi.*

php_cli_server_sapi_cli_server_ の接続面。
去年の「bridge 的な中間層」案はここで生かせます。

I. php_cli_server_log.*

ログ、タイミング、TTY 判定、補助ユーティリティ。


3. 実施フェーズ

フェーズ 1: 調査と no behavior change 分離

目的

レビューで受け入れられる地盤を作ること。

具体作業

  • 関数分類を最新版として更新する

  • callback 群の状態遷移表を作る

  • poll / log / utility のような比較的独立度の高い部分を別ファイルへ移す

  • status_compget_last_errorcli_header_value_dtordestroy_request_info などを「暫定 bridge / 保留関数」として棚上げ管理する。これらは去年の計画でも “グラデーション部” として問題意識がありました。

このフェーズでやらないこと

  • Stream API 化

  • llhttp 導入

  • request/response 構造体の全面刷新

成果物

  • 小さい PR

  • 「コード移動主体、挙動変更なし」

  • 読みやすい設計メモ


フェーズ 2: parser callback 直結の解体

目的

http_parser のイベントモデルを built-in server 本体から切り離すこと。

具体作業

  • php_cli_server_client_read_request_on_* 群を request_builder 層へ集約

  • message_beginheader_fieldheader_valuebodymessage_complete ごとに builder state を定義

  • client が parser の細粒度イベントを直接知らなくても済む形にする

  • parser 固有コードを parser_http_parser.c のような層へ閉じ込める

このフェーズの意味

ここが、http_parserllhttp 移行準備の本体です。
いきなり llhttp に差し替えるのではなく、まず callback 直結という構造問題を壊す のが先です。

成果物

  • request_builder 導入 PR

  • parser backend を隔離する PR


フェーズ 3: response path の再設計

目的

レスポンス関連の粒度の悪さを改善し、request 側と対称性のある構造にすること。

具体作業

  • append_http_status_line

  • append_essential_headers

  • add_response_header

  • php_cli_server_send_error_page

  • php_cli_server_client_write_response

などを分析し、以下へ分離する。

response builder

レスポンスの意味内容を組み立てる層
status, headers, body metadata, close policy を持つ

response emitter / sender

chunk, buffer, content sender, partial write を扱う層

去年の ResponseBuilder 構想と「ストーリーテラー関数」構想は、このフェーズで採用するのが自然です。

成果物

  • response builder 導入

  • sender 分離

  • 必要なら高水準 helper 関数の内部整理


フェーズ 4: transport と TLS 準備

目的

raw socket 前提を薄め、PHP Stream API 化のための交換点を作ること。

具体作業

  • accept/read/write/close を transport 層にまとめる

  • 現状は socket transport だけを実装

  • stream transport は別 PR または実験ブランチで準備

  • TLS 対応は transport/backend 差し替えとして語る

注意

この段階でも一気に全面 Streams 化はしない。
まずは transport abstraction を作る ことが目的です。


フェーズ 5: Poll backend 差し替え準備

目的

現在のイベントループから将来の Polling API への道筋を作ること。

具体作業

  • poller_add/remove/poll/iter を backend インターフェイスとして整理

  • 現状 backend を温存

  • 将来の Polling API backend を追加可能な形にする

注意

ここで Polling API 実装まで一気に入れなくてよいです。
まずは backend 境界を作る


フェーズ 6: llhttp backend 評価・置換

目的

upstream が停止した http_parser 依存を減らすこと。

具体作業

  • parser_http_parserparser_llhttp を比較可能にする

  • request builder 層のテストを使って parser backend の差分を検証

  • 挙動差分を局所化してレビューしやすくする

注意

llhttp 導入は、前段の builder 分離なしでは危険です。
このフェーズは必ず後ろに置きます。


4. 優先順位

実際の優先順位は次です。

  1. poll / log / utility の分離

  2. request builder 導入

  3. parser backend 隔離

  4. response builder / sender 分離

  5. transport abstraction

  6. llhttp backend

  7. Stream transport / TLS

  8. Polling API backend

この順番なら、去年の計画にあった response 改善と、今年の parser / TLS / polling 問題を 1 本の線でつなげられます。


5. PR 戦略

PR 1

polllog のファイル分割
狙い: no behavior change

PR 2

request callback 群の棚卸しと request_builder 下地追加
狙い: parser 直結の緩和

PR 3

http_parser 依存コードの adapter 化
狙い: llhttp 準備

PR 4

response builder / sender 分離
狙い: response path の明確化

PR 5

transport abstraction 追加
狙い: TLS 準備

PR 6

llhttp backend 実験または optional 導入
狙い: parser 更新

この粒度なら、1 回のレビューで抱える論点を減らせます。


6. この計画で意識するべき説明軸

upstream に説明するときの主軸は次です。

  • 現在の単一ファイルには複数の変更軸が混在している

  • parser backend 置換、TLS 対応、poll backend 差し替えのためには内部境界が必要

  • 最初の変更は no behavior change を守る

  • 高水準 API 提案ではなく、内部責務の分離である

去年の計画にあった httpserver.h 的な超高水準 API 構想は、今は前面に出さず、将来余地として心に留める程度でよいです。


7. 最初の作業項目

いま着手するなら、最初の TODO はこれです。

  • 関数分類を「移動候補」「保留」「境界関数」に再マークする

  • callback 10 個について、入力・更新対象・一時状態・完成通知を表にする

  • polllog の移動対象関数を具体名で決める

  • request_builder の最小責務を書く

  • ResponseBuilder を今すぐ実装するのではなく、response builder / sender の境界だけ文章化する

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment