PHPでHTTPレスポンスヘッダーを自由に制御(できなかった)

PHPでHTTPレスポンスヘッダーを制御しようと思うと...

PHP Modify HTTP Headers (Examples)

上記のように、header関数だらけで懇切丁寧に上書きすることになります。

ただ、これだと勝手に差し込まれている分のヘッダーが明示されないし、何だかちゃんとコントロールしてる感に欠けるのでヤだなーと思ってました。前にHTTPクライアントを実装したときに、fsockopenからfwriteで、リクエストをカキコカキコしていた覚えから、レスポンスヘッダーもイチからカキコカキコできないかと思い、調べてみた次第。

入出力ストリームからアクセスできないかな、と思ってトライ

PHP 入出力ストリーム でheaderを書いたことにならないかと期待してそれぞれ試してみました。

※ 今回はきっと、知ってる・分かってる方からしたら「あったりまえじゃん」的な内容なのだと思います。言い訳 lol

php://output

<?php
$out = fopen('php://output', 'w');
fwrite($out, "HTTP/1.1 418 I'm a Teapot\r\n");
fclose($out);
?>
HTTP/1.1 200 OK
Date: Mon, 25 Oct 2010 09:49:00 GMT
Server: Apache
X-Powered-By: PHP/5.2.14
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 57
Connection: close
Content-Type: text/html; charset=UTF-8

HTTP/1.1 418 I'm a Teapot

レスポンスボディ部分に書き込まれてしまいました。

php://stdout

<?php
$out = fopen('php://stdout', 'w');
fwrite($out, "HTTP/1.1 418 I'm a Teapot\r\n");
fclose($out);
?>
HTTP/1.1 200 OK
Date: Mon, 25 Oct 2010 09:50:03 GMT
Server: Apache
X-Powered-By: PHP/5.2.14
Vary: Accept-Encoding,User-Agent
Content-Encoding: gzip
Content-Length: 30
Connection: close
Content-Type: text/html; charset=UTF-8

ボディにもいかないあたり、標準出力の名の通り、php://stderr等と合わせてCLIやらエラーログ用の受け口だと思います。(詳細は未確認)

ob ( output buffering ? ) 系関数にも期待しましたが

この関数は出力のバッファリングをオンにします。 出力のバッファリングを有効にすると、 (ヘッダ以外の) スクリプトからの出力は実際には行われず、 代わりに内部バッファに保存されます。 PHP: ob_start - Manual

ヘッダ以外の出力、とのことなので、phpにおけるheader関数以外のoutputは、やっぱりボディの話のようです。

参考までに、PhpTipsに書かれている内容を流し見ても、やはりそのような結論に至るニュアンスがチラホラ。うーん残念。

オマケ php の PUTメソッドサポート

今回のHTTPヘッダー完全制御の道筋があるんじゃないかと、勝手に期待してしまったのは以下の項目を読んでいる最中でした。

PHP: PUT method support - Manual

<?php
$input = @file_get_contents('php://input');
@file_put_contents($path, $input);
?>

一通り試してみてから見直してみると、これでPUTのリクエストボディが input だって言うのだから、そりゃ output はレスポンスボディだよね、と納得。

オマケ2 出力予定なheaderの取得

どっちも似たような機能の関数ですが、前者はPHP5から。リクエストヘッダの最初の行は、双方のリストアップの対象ではないみたい。どういう意味でなんだろう。

あと、PHPで明示していない&リストアップもされていないヘッダが付与されているのは、Apacheが勝手につけてる分だろうか。PHP側で書いていなければ、Apacheがhttpd.conf等の設定如何で、付与してると勝手に推測。この辺のミドルウェア(?)周りの細かい挙動は、理解浅いなー。

<?php
header("HTTP/1.1 418 I'm a Teapot");
header("Content-Encoding: hogehoge");
var_dump(headers_list());
var_dump(apache_response_headers());
?>
HTTP/1.1 418 I'm a Teapot
Date: Mon, 25 Oct 2010 10:07:18 GMT
Server: Apache
X-Powered-By: PHP/5.2.14
Content-Encoding: none
Vary: User-Agent
Content-Length: 140
Connection: close
Content-Type: text/html; charset=UTF-8

array(2) {
  [0]=>
  string(24) "X-Powered-By: PHP/5.2.14"
  [1]=>
  string(22) "Content-Encoding: hogehoge"
}
array(2) {
  ["X-Powered-By"]=>
  string(10) "PHP/5.2.14"
  ["Content-Encoding"]=>
  string(8) "hogehoge"
}

今回は以上。ではでは。