Skip to content

Instantly share code, notes, and snippets.

@PurpleBooth
Last active March 3, 2024 14:22
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save PurpleBooth/81705c8cd172a436c4c381cb41bc2861 to your computer and use it in GitHub Desktop.
Save PurpleBooth/81705c8cd172a436c4c381cb41bc2861 to your computer and use it in GitHub Desktop.
Set the symfony _format property from the Accepts header based on what the serializer can support
<?php
declare(strict_types=1);
namespace PurpleBooth\Bundle\ExampleBundle\Controller\Api;
use PurpleBooth\Bundle\ExampleBundle\Entity\Example;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Serializer\Exception\ExceptionInterface;
class ExampleController extends Controller
{
/**
* @Route(
* "/api/example",
* name="example_api_post",
* methods={"post"}
* )
*
* @param Request $request
*
* @return Response
*/
public function createAction(Request $request): Response
{
$serializer = $this->get('serializer');
$outboundFormat = $request->getRequestFormat();
$inboundFormat = $request->getContentType();
if (!$serializer->supportsEncoding($outboundFormat)) {
return Response::create('', Response::HTTP_NOT_ACCEPTABLE);
}
if (!$serializer->supportsEncoding($inboundFormat)) {
return Response::create('', Response::HTTP_UNSUPPORTED_MEDIA_TYPE);
}
try {
/** @var Example $example */
$example = $serializer->deserialize(
$request->getContent(),
Example::class,
$inboundFormat
);
} catch (ExceptionInterface $e) {
return Response::create('', Response::HTTP_BAD_REQUEST);
}
$this->getDoctrine()->getManager()->persist($example);
$this->getDoctrine()->getManager()->flush();
return Response::create(
$serializer->serialize($example, $outboundFormat),
Response::HTTP_CREATED,
['Content-Type' => $request->getMimeType($outboundFormat)]
);
}
}
<?php
declare(strict_types=1);
namespace Purplebooth\Example\EventListener;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Serializer\Encoder\EncoderInterface;
/**
* Class FormatFromAcceptListener
*/
class FormatFromAcceptListener implements EventSubscriberInterface
{
/**
* @var EncoderInterface
*/
private $serializer;
/**
* FormatFromAcceptListener constructor.
*
* @param EncoderInterface $serializer
*/
public function __construct(EncoderInterface $serializer)
{
$this->serializer = $serializer;
}
/**
* @return array
*/
public static function getSubscribedEvents()
{
// must be registered after AddRequestFormatsListener
return [KernelEvents::REQUEST => ['onKernelRequest', 0]];
}
/**
* @param GetResponseEvent $event
*/
public function onKernelRequest(GetResponseEvent $event): void
{
$request = $event->getRequest();
$format = $request->get('_format');
if ($format == null) {
$accepts = $request->getAcceptableContentTypes();
foreach ($accepts as $accept) {
$format = $request->getFormat($accept);
if ($format !== null && $this->serializer->supportsEncoding($format)) {
$request->attributes->set('_format', $format);
break;
}
}
}
}
}
services:
purplebooth.listener.format_from_accept_listener:
class: Purplebooth\Example\EventListener\FormatFromAcceptListener
arguments: ['@serializer']
tags:
- { name: kernel.event_subscriber }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment