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のコントローラーコードなどを共有していただければ、原因を特定しやすくなります。お気軽にご相談ください。