0
votes

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.

Here is what I need it to do and how I've attempted to set it up:

When Authenticated

  • Any route requesting application/jsonshould hit the routes they have been setup for as usual.

  • Any route that is entered not requesting application/json should load a controller that renders a twig file containing all the JS for my single page app.

  • Any static resource that doesn't exist and ends looking for a symfony route eg [.js, .css, .jpeg, etc] should return 404.

When NOT Authenticated

  • Anything requesting application/json should return 403

  • Anything NOT requesting application/json should return to the login page

Here is what i've attempted so far:

  • Setup routes with the FOSRestBundle for each service

  • Setup a listener that returns the base controller html if the request isn't application/json

    if (!in_array('application/json', $request->getAcceptableContentTypes())) {
        $fakeRequest = $event->getRequest()->duplicate(
            null,
            null,
            array('_controller' => 'HvHDashboardBundle:Dashboard:index')
        );
        $controller = $this->resolver->getController($fakeRequest);
        $event->setController($controller);
    }
    
  • Setup a bunch of 'catch all' routes to fake a 404 if the static resource doesn't exist.

    # 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
    

Issues

  • This approach feels like a massive hack, and is not how the Symfony routing system is intended to work
  • 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.

Question:

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?

1

1 Answers

1
votes

Only make an API, no static pages at all. Trust me, I recently did a moderate sized API with Symfony and that's the way to go. It will simplify your backend security a lot, if you do not mix the API with static pages. Ofcourse you can still have static pages, if you want to have some sort of Landing page or something. but try not to mix them with the main app.

Even for login, do not make a static page, but instead have an api route that will validate username/password and return the user the auth token in response. One user can have multiple tokens for example (can be logged in at multiple locations), and the token is sent in the request headers everytime.

If the token is validated ok, symfony will know which user it belongs, so you will know the 'User'. If no token is present, it should return "Not Authenticated", and if token is invalid also something like that or 'Bad request'.

One thing that I had to do when doing with APIs is that I had to write a request listener to accept JSON content and transform it into request object, so I could access data with $request->request.

If you have any questions, let me know in comment and I can help.

As far as routing is concerned, follow the REST rules and you will be good to go.