Search code examples
symfonyfosrestbundle

Return a 'raw' response with FOSRestBundle


I'm in a bit of a pickle and I hope one of the more advanced Symfony / FOSRestBundle users can help me out with this.

FOSRestBundle returns responses as such:

<?xml version="1.0" encoding="UTF-8"?>
 <result>
  <entry>
  </entry>
 </result>

The thing is, I am storing complete XML blobs in my database because some other systems depend on it, which are as follows:

<profile updated="2015-03-04T10:00">
 <first_name>Peter</first_name>
 <last_name>Pan</last_name>
 <age>34</age>
 <department>Marketing</department>
 <job>Lead Marketing</job>
 <town>New York</town>
 <phone type="work">12345678910</phone>
 <email type="work">user@town.org</email>
</profile>

I store these as complete blobs, is there any way I can return these without having FOSRestBundle add the aforementioned stuff around my own XML?

If anything is unclear feel free to ask me for more information. Thanks in advance!


Solution

  • As in my comment you could send a response object with the content set to the XML and with the content type set to application/xml like..

    /** @var XMLModelInterface $xmlModel */
    /* $xmlModel populated from your database */
    $xmlModel = new XMLModel();
    
    $response = new Response(
        $xmlModel->getContent(),
        Response::HTTP_OK,
        array(
            'Content-Type' => 'application/xml',
        )
    );
    

    But to add to that, what you could do is set an event listener that listened for the kernel.view (Typical Purposes: Transform a non-Response return value from a controller into a Response) and convert your XMLModelInterface to a response. This would mean that you would only need to return an XMLModelInterface from your controller and you would only have one place to update if you wanted to change the way the response was handled.

    I haven't tested this so it might not be bang on correct but as far as I know it would work. I've used some info from FOSRestBundle and the SensionFrameworkExtraBundle so it should be alright.

    Event Subscriber

    class XMLModelResponseSubscriber implements EventSubscriberInterface
    {
        /**
         * Converts a returned XMLModelInterface to a Response object
         *
         * @param GetResponseForControllerResultEvent $event
         */
        public function onKernelView(GetResponseForControllerResultEvent $event)
        {
            // If controller result is not a XMLModelInterface ignore
            if (!is_a($event->getControllerResult(), 'Acme/SomeBundle/Model/XMLModelInterface')) {
                return;
            }
    
            $response = new Response(
                $event->getControllerResult()->getContent(),
                Response::HTTP_OK,
                array(
                    'Content-Type' => 'application/xml',
                )
            );
    
            $event->setControllerResult($response);
        }
    
        public static function getSubscribedEvents()
        {
            return array(
                KernelEvents::VIEW => 'onKernelView',
            );
        }
    }
    

    Services.yml

    services:
        acme.subscriber.xml_model_response:
            class: Acme\SomeBundle\EventSubscriber\XMLModelResponseSubscriber
            tags:
                - { name: kernel.event_subscriber }
    

    Then in your controller you would just do..

    /** @var XMLModelInterface $xmlModel */
    /* $xmlModel populated from your database */
    $xmlModel = new XMLModel();
    
    return $xmlModel;