Skip to content

Instantly share code, notes, and snippets.

@SerafimArts
Last active February 25, 2016 12:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SerafimArts/b0fa23961dd68f9af0ed to your computer and use it in GitHub Desktop.
Save SerafimArts/b0fa23961dd68f9af0ed to your computer and use it in GitHub Desktop.
<?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