CakePHPで開発をしていると、APIレスポンスに Content-Length
ヘッダーが付かずに困ることがあります。本記事では、Content-Length
が付与される条件や、それを妨げている要因、対策方法を詳しくまとめます。
Content-Length を付与させる条件と方法
1. Apache に削除させない
.htaccess
や 000-default.conf
に以下の記述があると、Apacheが Content-Length
を明示的に削除してしまいます。不要であれば削除しましょう。
Header unset Content-Length
Header set Transfer-Encoding "chunked"
2. Transfer-Encoding: chunked
を無効にする
チャンク転送が有効だと Content-Length
は使われません。無効にするには以下のように設定します。
Header unset Transfer-Encoding
SetEnv no-gzip 1
3. PHP側で出力サイズを明示する
単純なPHPスクリプトの場合:
<?php
$data = "Hello World!";
header('Content-Length: ' . strlen($data));
echo $data;
CakePHPのコントローラーで明示的に設定:
$this->response = $this->response
->withHeader('Content-Length', strlen($this->response->getBody()));
4. output_buffering
を有効にする
php.ini
でバッファリングを有効にしておくと、出力サイズを自動検出して Content-Length
を付けてくれます。
output_buffering = 4096
あるいは:
output_buffering = On
Docker使用時は /usr/local/etc/php/php.ini
などの場所にも注意してください。
5. mod_deflate / gzip の影響を防ぐ
圧縮が有効だと Transfer-Encoding
に変わり Content-Length
が除外されることがあります。
SetEnv no-gzip 1
チェックコマンド一覧
curl -i http://cakephp.test/
apachectl -M | grep headers
php -i | grep output_buffering
レスポンスに Content-Length: XXX
が含まれていれば、付与は成功しています。
Content-Length を付けたい理由
- CDNやロードバランサーでキャッシュ制御をしたい
- クライアント側で進捗バーを表示したい
- セキュリティポリシーやWAFでの要件に対応したい
よくある表示されない理由とその確認方法
1. レスポンスボディが空またはnull
本文が何も出力されていないと、Content-Length
は出力されません。
確認方法:
curl -i http://cakephp.test/
2. ApacheがFastCGIで動作している
mod_php ではなく FastCGI や php-fpm 経由で動作していると Content-Length
が省略されることがあります。
確認方法:
apachectl -V | grep -i mpm
または phpinfo()
で Server API
を確認(例:FPM/FastCGI)
3. Dockerリバースプロキシの影響
nginx
や Traefik
などがプロキシとして動作していると、ヘッダーが上書きされている可能性があります。
確認方法:
docker-compose ps
4. PHPが自動でchunked転送に切り替えている
バッファが使われていないと Content-Length
を使わず Transfer-Encoding: chunked
に切り替わることがあります。
対策例:
ob_start();
echo "Content";
$output = ob_get_clean();
header('Content-Length: ' . strlen($output));
echo $output;
5. CakePHPがキャッシュ制御をしている
CakePHP の withDisabledCache()
やミドルウェアでキャッシュ制御が行われていると Content-Length
が抑制される場合があります。
6. HTTP/2使用時にcurlで表示されない
HTTP/2ではフレーム単位で通信されるため、Content-Length
が表示されなくても正常です。
HTTP/1.1を指定して確認:
curl -i --http1.1 http://cakephp.test/
7. PHPで出力前にWarningやNoticeが発生している
ヘッダー送信前にエラー出力があると、Content-Length
が送信されないことがあります。
最終確認:ヘッダー送信のテンプレートスクリプト
CakePHPを通さずに info.php
のようなスクリプトを用意し、最小構成で確認します。
<?php
$data = "Test Content";
header('Content-Length: ' . strlen($data));
echo $data;
curl -i http://cakephp.test/info.php
チェックリストまとめ
項目 | チェック内容 |
---|---|
レスポンスが空でないか | 本文ありであることを確認 |
PHPモードの確認 | mod_php or php-fpm をチェック |
Proxyによる上書き | nginx , Traefik などが動作していないか |
Transfer-Encoding の有無 | curl --http1.1 で確認 |
CakePHPのミドルウェア | キャッシュ制御が有効か |
HTTP/2 の仕様 | curl --http1.1 でフォールバックして確認 |
Apacheモジュール | mod_headers , mod_deflate などの有無 |
PHPバッファ設定 | output_buffering , zlib.output_compression を確認 |
さいごに
Apacheの設定、PHPの動作モード、CakePHPの挙動などが複雑に絡み合うため、状況によって対策が異なります。
もし可能であれば 000-default.conf
や Dockerfile
、CakePHPのコントローラーコードなどを共有していただければ、原因を特定しやすくなります。お気軽にご相談ください。
コメントを残す