Last active
July 22, 2020 12:41
-
-
Save alexwilson/5354d78c13c38ed103e87e6430f5ee98 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php declare(strict_types=1); | |
namespace AppBundle\EventListener; | |
use Symfony\Component\EventDispatcher\EventSubscriberInterface; | |
use Symfony\Component\HttpKernel\Event\{GetResponseEvent, FilterResponseEvent}; | |
use Symfony\Component\HttpKernel\KernelEvents; | |
use Symfony\Component\HttpFoundation\HeaderBag; | |
class SpecialistPreflightLegacyHandler implements EventSubscriberInterface | |
{ | |
// Try to run as soon as possible. | |
const HIGH_PRIORITY_REQUEST = 999999; | |
/** | |
* {@inheritDoc} | |
*/ | |
public static function getSubscribedEvents(): array | |
{ | |
return [ | |
KernelEvents::REQUEST => [ | |
['recordRequestedHeaders', self::HIGH_PRIORITY_REQUEST], | |
['parseSpecialistFlags', self::HIGH_PRIORITY_REQUEST-1] | |
], | |
KernelEvents::RESPONSE => 'varyOnRequestedSpecialistHeaders' | |
]; | |
} | |
/** | |
* Replace the HeaderBag with one that keeps track of which Headers are read. | |
* | |
* @param GetResponseEvent $event | |
* | |
* @return void | |
*/ | |
public function recordRequestedHeaders(GetResponseEvent $event) | |
{ | |
$request = $event->getRequest(); | |
$request->originalHeaderBag = $request->headers; | |
/** | |
* Wrap the Request object with a shim that records all property accesses.. | |
*/ | |
$request->headers = new class($request->originalHeaderBag->all()) extends HeaderBag { | |
/** | |
* @var string[] | |
*/ | |
protected $varyHeaders = []; | |
/** | |
* {@inheritDoc} | |
*/ | |
public function all() | |
{ | |
$this->varyHeaders += parent::keys(); | |
return parent::all(); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function keys() | |
{ | |
$keys = parent::keys(); | |
$this->varyHeaders += $keys; | |
return $keys; | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function get($key, $default = null, $first = true) | |
{ | |
$this->varyHeaders[] = $key; | |
return parent::get($key, $default, $first); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function has($key) | |
{ | |
$this->varyHeaders[] = $key; | |
return parent::has($key); | |
} | |
/** | |
* {@inheritDoc} | |
*/ | |
public function contains($key, $value) | |
{ | |
$this->varyHeaders[] = $key; | |
return parent::contains($key, $value); | |
} | |
/** | |
* @return string[] An array of headers we may Vary on. | |
*/ | |
public function getVaryHeaders() | |
{ | |
return array_unique($this->varyHeaders); | |
} | |
}; | |
} | |
/** | |
* Interpret KV flag data of format "KEY=VALUE,KEY=VALUE" passed in 'Specialist-Flags' header | |
* | |
* @param GetResponseEvent $event | |
* @return void | |
*/ | |
public function parseSpecialistFlags(GetResponseEvent $event) | |
{ | |
$request = $event->getRequest(); | |
$request->flags = new HeaderBag(); | |
if ($flags = $request->headers->get('Specialist-Flags')) { | |
parse_str(str_replace(',', '&', $flags), $parsedFlags); | |
foreach ($parsedFlags as $key => $value){ | |
$sanitizeFlagValue = filter_var($value, FILTER_VALIDATE_BOOLEAN); | |
$request->flags->set($key, $sanitizeFlagValue); | |
} | |
} | |
} | |
/** | |
* Automatically tags a FilterResponseEvent with the correct Vary based on what we have read during a request. | |
* | |
* @param FilterResponseEvent $event | |
* | |
* @return void | |
*/ | |
public function varyOnRequestedSpecialistHeaders(FilterResponseEvent $event): void | |
{ | |
$request = $event->getRequest(); | |
$response = $event->getResponse(); | |
foreach ($request->headers->getVaryHeaders() as $header) { | |
if (0 === strpos($header, 'Specialist')) { | |
$response->setVary($header, false); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment