Unfortunately you cannot specify multiple domains. You either need to create an .htaccess/apache rule: credit which may or may not work for you if you don’t have access to apache modules.
<FilesMatch "\.(ttf|otf|eot|woff|js|css|woff2)$">
<IfModule mod_headers.c>
SetEnvIf Origin "^http(s)?:\/\/(www\.|dev\.|local\.)?(domain\.com|domain2\.com)$" AccessControlAllowOrigin=$0
Header add Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin
</IfModule>
</FilesMatch>
or have a wildcard which doesn’t make sense to me. It seems to either be an all or very restrictive approach, which then most dev’s will opt for the very easy wildcard ‘*’ approach.
I wrote a Slim middleware, (which can be installed via composer) since I needed the ability to allow my API to be accessed by multiple domains and restrict what methods I allow. I also prefer having this ability in php instead of an .htaccess file. This is a slightly modified version of what I’m using since I’m using Slim’s DI Container. I moved all the settings into the same file. In other words make sure to TEST TEST TEST it as I’m not using this exact implementation.
CorsMiddleware.php
<?php
namespace Middleware;
class CorsMiddleware
{
/**
* Associative array with domain => [allowed methods] list
* @var array
*/
protected $cors = [
'https://somedomain.com' => ['GET', 'POST'],
'http://somedomain.com' => ['GET', 'POST'],
'https://dev.somedomain.com' => ['DELETE', 'PUT', 'POST']
];
/**
* Middleware invokable class
*
* @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request
* @param \Psr\Http\Message\ResponseInterface $response PSR7 response
* @param callable $next Next middleware
*
* @return \Psr\Http\Message\ResponseInterface
*/
public function run($request, $response, $next)
{
$response = $next($request, $response);
$origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : 'none';
return $this->getResponse($response, $origin, $this->cors);
}
/**
* Gets allow method string of comma separated http verbs
* @param string $origin origin domain
* @param array $cors access list with methods
* @return string comma delimited string of methods
*/
private function getAllowedMethodsString($cors, $origin)
{
$methods = $cors[$origin];
if (is_array($methods)) {
$methods = implode(', ', $methods);
}
return $methods;
}
/**
* Gets the proper origin header value
* @param array $cors cors config
* @param string $origin http_origin
* @return string origin value
*/
private function getOriginHeader($cors, $origin)
{
if (isset($cors['*'])) {
return '*';
}
return $origin;
}
/**
* Gets appropriate response object
* @param \Psr\Http\Message\ResponseInterface $response PSR7 Response
* @param string $origin origin domain
* @param array $cors access list with methods
* @return \Psr\Http\Message\ResponseInterface $response PSR7 Response
*/
private function getResponse($response, $origin, $cors)
{
if (isset($cors['*'])) {
$origin = '*';
}
if (!isset($cors[$origin])) {
return $response;
}
return $response
->withHeader('Access-Control-Allow-Origin', $this->getOriginHeader($cors, $origin))
->withHeader('Access-Control-Allow-Methods', $this->getAllowedMethodsString($cors, $origin));
}
}
index.php
.
.
$app->add('\Middleware\CorsMiddleware:run');
.
.
You may wonder why Allow-Methods may not appear to be working when you test ( you will test… right?!) , this got me as well, and I found the answer:
Simple cross-origin requests generated outside this specification (such as cross-origin form submissions using GET or POST or cross-origin GET requests resulting from script elements) typically include user credentials, so resources conforming to this specification must always be prepared to expect simple cross-origin requests with credentials.
Because of this, resources for which simple requests have significance other than retrieval must protect themselves from Cross-Site Request Forgery (CSRF) by requiring the inclusion of an unguessable token in the explicitly provided content of the request.
credit
Also mind your protocols! if you want http and https you will need to include both in the $cors list. Hope that helps.