SlimでJSONを返す際のCORSの記述

PHPフレームワークのSlimを使う機会があったのでメモ。 やりたかったこととしては、AJAX通信によるJSONのAPIを実装すること。 以前Abu al-Haulの際にDietCakeを使った時と同じような形です。 ちなみに、Slimに関してはSlimそのままではなく、slimphp/Slim-Skeletonを使用しています。 今回は「composer startlocalhost:8080でAPI側が待ち受けており、そこにlocalhostのJSからAJAXでリクエストが飛んでくる」という状況を想定しています。 その上でsrc/route.phpに以下のような記述を追加。
<?php

use Slim\App;
use Slim\Http\Request;
use Slim\Http\Response;

return function (App $app) {
    $container = $app->getContainer();

    $app->get('/', function (Request $request, Response $response, array $args) use ($container) {
        $response = $response
            ->withHeader('Access-Control-Allow-Origin', 'http://localhost') //リクエスト元のオリジン
            ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
            ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
    });
};
Slimのドキュメントそのままですが、これでCORSをクリアし、JS側に処理させることができることを確認しました。 なお、SlimはwithJsonメソッドがあり、return $response->withJson(<ARRAY>, <HTTP_STATUS_CODE>);という形でJSON形式のレスポンスを返すことができるとのことで、これも楽だなー、と思いました。

余談

    $app->get('/', function (Request $request, Response $response, array $args) use ($container) {
        $response = $response
            ->withHeader('Access-Control-Allow-Origin', 'http://localhost:8080')
            ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
            ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
CORSのルールをさっぱり忘れていて、途中こんな書き方(Access-Control-Allow-OriginにAPI側のhttp://localhost:8080を記述`)をすると、
Access to XMLHttpRequest at ‘http://localhost:8080/’ from origin ‘http://localhost’ has been blocked by CORS policy: The ‘Access-Control-Allow-Origin’ header has a value ‘http://localhost:8080’ that is not equal to the supplied origin.

で怒られました。さらに、
    $app->get('/', function (Request $request, Response $response, array $args) use ($container) {
        $response = $response
            ->withHeader('Access-Control-Allow-Origin', 'http://localhost:8080 always')
            ->withHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type, Accept, Origin, Authorization')
            ->withHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
これだと
The ‘Access-Control-Allow-Origin’ header contains multiple values ‘http://localhost:8080 always’, but only one is allowed.
という内容で怒られました。メモ。

参考

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。