Laravelでjsonを返却するときにContent-Typeがapplication/jsonにならない、ヘッダー情報に不要なものが付与される時の対応
2018-01-29Laravel プロジェクトで作成した API で JSON を返却する際に、ヘッダーに余分なものが付いていたので、その対応方法です。
今回jsonを返却するときの要件として、
- ステータスコードを指定したい
Cache-Control
はno-cache
のみ指定したいSet-Cookie
は付与したくない
というのがあります。
Laravelの response ファザードを使用してjsonを返す場合
<?php
public function test_json($response_code = 200)
{
$res = ['foo' => 'bar'];
$json = json_encode($res);
return response($json, $response_code)
->header('Cache-Control', 'no-cache')
->header('Content-Type', 'application/json')
->header('Content-Length', strlen($json));
}
test_json(400);
curlでtest_json()
を実行するurlを叩いた結果が下記。
$ curl -v http://localhost/path/to/test_json
> GET /path/to/test_json HTTP/1.1
> Host: localhost
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Date: Wed, 27 Dec 2017 04:19:00 GMT
< Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.13 PHP/7.1.1 mod_ssl/2.2.31 OpenSSL/1.0.2j DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0
< X-Powered-By: PHP/7.1.1
< Cache-Control: no-cache, private
< Content-Length: 13
< Set-Cookie: XSRF-TOKEN=eyJpd....RhMTUifQ%3D%3D; expires=Wed, 27-Dec-2017 04:54:07 GMT; Max-Age=7200; path=/
< Set-Cookie: 91bb0181f7d...908eb59101d6226=eyJ....ODgyIn0%3D; expires=Thu, 28-Dec-2017 02:54:07 GMT; Max-Age=86400; path=/; HttpOnly
< Connection: close
< Content-Type: application/json
<
* Closing connection 0
{"foo":"bar"}
一見問題なさそうですが、まず Cache-Control
に private
が付いている。ぐぐってみると別に問題なさそうですが、気持ち悪いです。
あと、Set-Cookie
で不要なものが付いている。これに関してはミドルウェアでごちゃごちゃやると付与しないように出来るみたいです。今回はやりません。
純粋にPHPの関数だけでjsonを返却する場合
<?php
public function test_json($response_code = 200)
{
$res = ['foo' => 'bar'];
$json = json_encode($res);
http_response_code($response_code);
header('Cache-Control: no-cache');
header('Content-Type: application/json');
header('Content-Length: '.strlen($json));
echo $json;
}
test_json(400);
urlを叩きます。
$ curl -v http://localhost/path/to/test_json
> GET /path/to/test_json HTTP/1.1
> Host: localhost
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 27 Dec 2017 04:30:58 GMT
< Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.13 PHP/7.1.1 mod_ssl/2.2.31 OpenSSL/1.0.2j DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0
< X-Powered-By: PHP/7.1.1
< Cache-Control: no-cache, no-cache
< Set-Cookie: XSRF-TOKEN=eyJpd....RhMTUifQ%3D%3D; expires=Wed, 27-Dec-2017 04:54:07 GMT; Max-Age=7200; path=/
< Set-Cookie: 91bb0181f7d...908eb59101d6226=eyJ....ODgyIn0%3D; expires=Thu, 28-Dec-2017 02:54:07 GMT; Max-Age=86400; path=/; HttpOnly
< Content-Length: 13
< Content-Type: text/html; charset=UTF-8
<
* Connection #0 to host localhost left intact
{"foo":"bar"}
HTTP/1.1 200 OK
?
Cache-Control: no-cache, no-cache
??
Content-Type: text/html
???
Set-Cookie
残ったまま????
色々とおかしいです。
挙動的には、echo
したあとにLaravel側の何かしらの処理が動いている感じです。多分。
しばらく悩んだ末の解決策
<?php
public function test_json($response_code = 200)
{
$res = ['foo' => 'bar'];
$json = json_encode($res);
http_response_code($response_code);
header('Cache-Control: no-cache');
header('Content-Type: application/json');
header('Content-Length: '.strlen($json));
echo $json;
exit();
}
test_json(400);
echo
したあとに exit()
するだけです。
$ curl -v http://localhost/path/to/test_json
> GET /path/to/test_json HTTP/1.1
> Host: localhost
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Date: Wed, 27 Dec 2017 04:44:56 GMT
< Server: Apache/2.2.31 (Unix) mod_wsgi/3.5 Python/2.7.13 PHP/7.1.1 mod_ssl/2.2.31 OpenSSL/1.0.2j DAV/2 mod_fastcgi/2.4.6 mod_perl/2.0.9 Perl/v5.24.0
< X-Powered-By: PHP/7.1.1
< Cache-Control: no-cache
< Content-Length: 13
< Connection: close
< Content-Type: application/json
<
* Connection 0
{"foo":"bar"}
長時間悩んだときの解決策って、だいたいあっさりしてます。
comments powered by Disqus