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