Last Updated: February 25, 2016
·
3.122K
· raphaelstolt

JSONP(ad) Silex responses via an after middleware

One approach to auto transform Silex responses into JSONP(adding) responses via an after middleware. It's based on the Content-Type of the original reponse coming from the matching application route.

<?php
use Symfony\Component\HttpFoundation\JsonResponse;

$app->after(function (Request $req, Response $res) {
  if ($req->get('jsonp_callback') !== null 
      && $req->getMethod() === 'GET')
  {
    $contentType = $res->headers->get(
      'Content-Type'
    );
    $jsonpContentTypes = array(
      'application/json',
      'application/json; charset=utf-8',
      'application/javascript',
    );
    if (!in_array($contentType, $jsonpContentTypes)) 
    {
      // Don't touch the response
      return;
    }
    if ($res instanceof JsonResponse) {
      $res->setCallBack($req->get('jsonp_callback'));
    } else {
      $res->setContent(
        $req->get('jsonp_callback') 
          . '(' . $res->getContent() . ');'
      );
    }
  }
});

Another approach would be to guard or compare the current route against a set of JSONPable route patterns, which might come from a configuration; which, however, need to be maintained.

Yet another approach provided by @igorwesome would be to use the native Symfony\Component\HttpFoundation\JsonResponse directly inside a matching route, I guess.

<?php  
use Silex\Application,
  Symfony\Component\HttpFoundation\JsonResponse,
  Symfony\Component\HttpFoundation\Request;

$app->get('/ex', function(Application $a, Request $r) {
  if ($r->get('jsonp_callback') !== null 
      && $r->getMethod() === 'GET')
  {
    $data = $a['service_xy']->getDataXyz();
    $resp = new JsonResponse($data);
    return $resp->setCallback(
      $r->get('jsonp_callback')
    );
  }
});