title: Symfony routing for a REST API / Single page app
body: <p>I'm trying to setup routes for my Symfony2 single page app and I'm not sure how to go about it correctly without it feeling super hacky.</p>
  
  <p>Here is what I need it to do and how I've attempted to set it up:</p>
  
  <p><strong>When Authenticated</strong></p>
  
  <ul>
  <li><p>Any route requesting <code>application/json</code>should hit the routes they have been setup for as usual.</p></li>
  <li><p>Any route that is entered not requesting <code>application/json</code> should load a controller that renders a twig file containing all the JS for my single page app.</p></li>
  <li><p>Any static resource that doesn't exist and ends looking for a symfony route eg [.js, .css, .jpeg, etc] should return 404.</p></li>
  </ul>
  
  <p><strong>When NOT Authenticated</strong></p>
  
  <ul>
  <li><p>Anything requesting <code>application/json</code> should return 403</p></li>
  <li><p>Anything NOT requesting <code>application/json</code> should return to the login page</p></li>
  </ul>
  
  <p><strong>Here is what i've attempted so far:</strong></p>
  
  <ul>
  <li><p>Setup routes with the FOSRestBundle for each service</p></li>
  <li><p>Setup a listener that returns the base controller html if the request isn't <code>application/json</code></p>
  
  <pre><code>if (!in_array('application/json', $request-&gt;getAcceptableContentTypes())) {
      $fakeRequest = $event-&gt;getRequest()-&gt;duplicate(
          null,
          null,
          array('_controller' =&gt; 'HvHDashboardBundle:Dashboard:index')
      );
      $controller = $this-&gt;resolver-&gt;getController($fakeRequest);
      $event-&gt;setController($controller);
  }
  </code></pre></li>
  <li><p>Setup a bunch of 'catch all' routes to fake a 404 if the static resource doesn't exist.</p>
  
  <pre><code># routing.yml
  # Catch any files that are meant to be their own static resource and return 404  
  catch_all_fail:
      pattern:  /{uri}.{_format}
      defaults: { _controller: MyBundle:Dashboard:return404 }
      requirements:
          _format: js|hbs|css|jpg|gif|jpeg|png
  </code></pre></li>
  </ul>
  
  <p><strong>Issues</strong></p>
  
  <ul>
  <li>This approach feels like a massive hack, and is not how the Symfony routing system is intended to work</li>
  <li>The base controller page is returned even if you aren't authenticated because the type listener is being hit before the security context and forcing that controller to render.</li>
  </ul>
  
  <p><strong>Question:</strong></p>
  
  <p>How do other solve this issue with routing and single page apps with Symfony where they initially need to render HTML with twig, then JS takes over and requests JSON?</p>