Last active
February 25, 2016 12:36
-
-
Save SerafimArts/b0fa23961dd68f9af0ed 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 | |
/** | |
* This file is part of API package. | |
* | |
* @author Serafim <nesk@xakep.ru> | |
* @date 24.02.2016 16:23 | |
* | |
* For the full copyright and license information, please view the LICENSE | |
* file that was distributed with this source code. | |
*/ | |
namespace Interfaces\Http\Middleware; | |
use Core\DataSerializer\SerializerContract; | |
use Illuminate\Http\Request; | |
use Illuminate\Http\Response; | |
use Illuminate\Routing\Route; | |
use Illuminate\Routing\Router; | |
use Illuminate\Support\Str; | |
use Symfony\Component\HttpKernel\Exception\HttpException; | |
use Symfony\Component\Serializer\Exception\UnexpectedValueException; | |
/** | |
* Class ResponseDataSerialize | |
* @package Interfaces\Http\Middleware | |
*/ | |
class ResponseDataSerialize | |
{ | |
const DEFAULT_OUTPUT_FORMAT = 'json'; | |
/** | |
* @var SerializerContract | |
*/ | |
protected $serializer; | |
/** | |
* @var Router | |
*/ | |
protected $router; | |
/** | |
* ResponseDataSerialize constructor. | |
* @param SerializerContract $serializer | |
* @param Router $router | |
*/ | |
public function __construct(SerializerContract $serializer, Router $router) | |
{ | |
$this->serializer = $serializer; | |
$this->router = $router; | |
} | |
/** | |
* @param Request $request | |
* @param \Closure $next | |
* @return Response | |
* @throws \InvalidArgumentException | |
*/ | |
public function handle(Request $request, \Closure $next) | |
{ | |
$format = $this->getDesiredOutputFormat($request); | |
/** @var Response $response */ | |
try { | |
$response = $next($request); | |
$this->checkOutputFormat($format); | |
} catch (HttpException $e) { | |
$response = Response::create($e, $e->getStatusCode(), $e->getHeaders()); | |
} catch (\Exception $e) { | |
$response = Response::create($e, 500); | |
} | |
return $this->serializeResponseContent($response, $format); | |
} | |
/** | |
* @param $format | |
* @throws UnexpectedValueException | |
*/ | |
protected function checkOutputFormat($format) | |
{ | |
if (!$this->serializer->supportsDecoding($format)) { | |
$wantsFormat = $format; | |
$format = static::DEFAULT_OUTPUT_FORMAT; | |
throw new UnexpectedValueException( | |
sprintf('Serialization for the format "%s" is not supported', $wantsFormat) | |
); | |
} | |
} | |
/** | |
* @param Request $request | |
* @return string | |
*/ | |
protected function getDesiredOutputFormat(Request $request) | |
{ | |
// Resolve by Accept header | |
$acceptable = $request->getAcceptableContentTypes(); | |
if (array_key_exists(0, $acceptable)) { | |
return $this->getFormatByAcceptable($acceptable[0]); | |
} | |
// Try to resolve by extension | |
/** @var Route $route */ | |
$route = $this->router->current(); | |
$declaredExtension = $route->getParameter('ext', '.' . static::DEFAULT_OUTPUT_FORMAT); | |
return Str::substr($declaredExtension, 1); | |
} | |
/** | |
* @param string $acceptable | |
* @return string | |
*/ | |
public function getFormatByAcceptable($acceptable) | |
{ | |
switch (true) { | |
case Str::contains($acceptable, ['/json', '+json']): | |
return 'json'; | |
case Str::contains($acceptable, ['/yaml', '/x-yaml']): | |
return 'yaml'; | |
case Str::contains($acceptable, ['/xml']): | |
return 'xml'; | |
} | |
return static::DEFAULT_OUTPUT_FORMAT; | |
} | |
/** | |
* @param Response $response | |
* @param $format | |
* @return Response | |
* @throws \InvalidArgumentException | |
*/ | |
protected function serializeResponseContent(Response $response, $format) | |
{ | |
$content = $this->serializer->serialize($response->getOriginalContent(), $format); | |
$response->setContent($content); | |
// Overwrite response headers | |
$headers = $this->getHeadersByFormat($format); | |
foreach ($headers as $header => $value) { | |
$response->headers->set($header, $value); | |
} | |
return $response; | |
} | |
/** | |
* @param $format | |
* @return array | |
*/ | |
public function getHeadersByFormat($format) | |
{ | |
switch ($format) { | |
case 'yml': | |
case 'yaml': | |
return ['Content-Type' => 'application/x-yaml']; | |
case 'json': | |
return ['Content-Type' => 'application/json']; | |
case 'xml': | |
return ['Content-Type' => 'text/xml']; | |
} | |
return ['Content-Type' => 'text/plain']; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment