Skip to content

Commit

Permalink
Breaking change: Replace headers configured in `settings.responseHead…
Browse files Browse the repository at this point in the history
…ers`

- Response headers defined in `settings.responseHeaders` will no longer be merged with the previous header value, but will replace them
- Add support for `settings.defaultResponseHeaders` to define headers that will be set if the response does **not** already has that header
- Add CORS to the Header constants
- Add visibility for the Header constants
  • Loading branch information
cundd committed Mar 13, 2019
1 parent 2a0ea1b commit 3589149
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 38 deletions.
61 changes: 40 additions & 21 deletions Classes/Dispatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Cundd\Rest;

use Cundd\Rest\Dispatcher\DispatcherInterface;
use Cundd\Rest\Http\Header;
use Cundd\Rest\Http\RestRequestInterface;
use Cundd\Rest\Log\LoggerInterface;
use Cundd\Rest\Router\ResultConverter;
Expand Down Expand Up @@ -221,27 +222,12 @@ public static function getSharedDispatcher()
*/
private function addAdditionalHeaders(ResponseInterface $response)
{
$additionalResponseHeaders = $this->objectManager
->getConfigurationProvider()
->getSetting('responseHeaders', null);
$configurationProvider = $this->objectManager->getConfigurationProvider();
$fixedResponseHeaders = $configurationProvider->getSetting('responseHeaders', null);
$defaultResponseHeaders = $configurationProvider->getSetting('defaultResponseHeaders', null);

if (!is_array($additionalResponseHeaders)) {
return $response;
}

foreach ($additionalResponseHeaders as $responseHeaderType => $value) {
if (is_string($value)) {
$response = $response->withAddedHeader(
$responseHeaderType,
$value
);
} elseif (is_array($value) && array_key_exists('userFunc', $value)) {
$response = $response->withAddedHeader(
rtrim($responseHeaderType, '.'),
GeneralUtility::callUserFunction($value['userFunc'], $value, $this)
);
}
}
$response = $this->addHeaders($response, $defaultResponseHeaders, false);
$response = $this->addHeaders($response, $fixedResponseHeaders, true);

return $response;
}
Expand All @@ -256,7 +242,7 @@ private function addCorsHeaders(RestRequestInterface $request, ResponseInterface

foreach ($allowedOrigins as $allowedOrigin) {
if ($allowedOrigin === $origin) {
return $response->withHeader('Access-Control-Allow-Origin', $allowedOrigin);
return $response->withHeader(Header::CORS_ORIGIN, $allowedOrigin);
}
}
}
Expand Down Expand Up @@ -300,4 +286,37 @@ private function dispatchInternal(RestRequestInterface $request, ResponseInterfa

return $newResponse;
}

/**
* @param ResponseInterface $response
* @param array|null $defaultResponseHeaders
* @param bool $overwrite
* @return ResponseInterface
*/
private function addHeaders(
ResponseInterface $response,
?array $defaultResponseHeaders,
bool $overwrite
): ResponseInterface {
foreach ((array)$defaultResponseHeaders as $responseHeaderType2 => $value2) {
// If the header is already set skip it unless `$overwrite` is TRUE
if (!$overwrite && $response->getHeaderLine($responseHeaderType2)) {
continue;
}

if (is_string($value2)) {
$response = $response->withHeader(
$responseHeaderType2,
$value2
);
} elseif (is_array($value2) && array_key_exists('userFunc', $value2)) {
$response = $response->withHeader(
rtrim($responseHeaderType2, '.'),
GeneralUtility::callUserFunction($value2['userFunc'], $value2, $this)
);
}
}

return $response;
}
}
22 changes: 13 additions & 9 deletions Classes/Http/Header.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@
*/
abstract class Header
{
const CONTENT_ENCODING = 'Content-Encoding';
const CACHE_CONTROL = 'Cache-Control';
const LAST_MODIFIED = 'Last-Modified';
const EXPIRES = 'Expires';
const ETAG = 'ETag';
const CONTENT_TYPE = 'Content-Type';
const CONTENT_LENGTH = 'Content-Length';
public const CONTENT_ENCODING = 'Content-Encoding';
public const CACHE_CONTROL = 'Cache-Control';
public const LAST_MODIFIED = 'Last-Modified';
public const EXPIRES = 'Expires';
public const ETAG = 'ETag';
public const CONTENT_TYPE = 'Content-Type';
public const CONTENT_LENGTH = 'Content-Length';

public const CORS_ORIGIN = 'Access-Control-Allow-Origin';
public const CORS_METHODS = 'Access-Control-Allow-Methods';
public const CORS_CREDENTIALS = 'Access-Control-Allow-Credentials';

// This header will be sent if the response has been cached by the REST extension
const CUNDD_REST_CACHED = 'Cundd-Rest-Cached';
public const CUNDD_REST_CACHED = 'Cundd-Rest-Cached';

// This header can be set to prevent the REST extension from caching a response
const CUNDD_REST_NO_CACHE = 'Cundd-Rest-No-Cache';
public const CUNDD_REST_NO_CACHE = 'Cundd-Rest-No-Cache';
}
26 changes: 18 additions & 8 deletions ext_typoscript_setup.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,24 @@ plugin.tx_rest.settings {
}
}

# You may add custom response headers, see example below
#responseHeaders {
# Access-Control-Allow-Origin = example.com
# Access-Control-Allow-Methods = GET, POST, OPTIONS, DELETE
#}
#cors.allowedOrigins {
# 0 = http://localhost:3000
#}
# Configure a set of default response headers that will be set if the response does **not** already contain them
# defaultResponseHeaders {
# Access-Control-Allow-Credentials = true
# Access-Control-Allow-Methods = GET, POST, OPTIONS, DELETE
# }

# Overwrite the response's headers with the following ones
# responseHeaders {
# Access-Control-Allow-Credentials = true
# Access-Control-Allow-Methods = GET, POST, OPTIONS, DELETE
# }

# Define a list of allowed origins:
# If the request's `Origin`-header matches one of the listed origins, it will be whitelisted in the
# `Access-Control-Allow-Origin`-header of the response
# cors.allowedOrigins {
# 0 = http://localhost:3000
# }

# This is not defined here to allow easy customization in third party extensions TypoScript setup
# cacheLifetime = -1
Expand Down

0 comments on commit 3589149

Please sign in to comment.