1

I have an action in Symfony2 controller that is sending out a response back to the client (as detailed here). After the function sends out the response, I have an event subscriber that listens for onkernelTerminate event since I'll be doing some heavy work after the response is sent to the client.

Everything seems to be working normally for the part that's doing the heavy work except that there's line in the code that is referencing a service that utilizes Session, which needs it for storing tokens and eventually communicating with an external API.

The error is of course: Failed to start the session because headers have already been sent.

Is there a way to start a Session even headers have been sent? Or what would be a better approach to handle this issue?

Community
  • 1
  • 1
user1370897
  • 503
  • 8
  • 15
  • 2
    You can't open a session after headers were sent, but you could open it before they're sent and probably write to the session later on... – ceejayoz Sep 11 '15 at 19:59
  • @ceejayoz What you mean open it before headers are sent? Sounds promising, but please provide an example. – user1370897 Sep 11 '15 at 20:13
  • 1
    is there a reason you chose onKernelTerminate event ? why not onKernelResponse event? – wonde Sep 11 '15 at 21:34
  • @wonde because I need to close the connection with the client or rather sent them a response first, and the continue processing. Will a make it difference? – user1370897 Sep 11 '15 at 21:50
  • >> because I need to close the connection with the client or rather sent them a response first... Why? I mean i even think this is not possible because your server (apache?) will send the response after your script has ended? – Frank B Sep 12 '15 at 09:04
  • Is there a way to decouple that data to database? Or some in-memory database at least? – Jovan Perovic Sep 12 '15 at 11:31
  • @Frankbeen Reason I needed to send the response first to the client is because I have an incoming AWS SNS message and if my server is taking its time processing what it needs to process (heavy processing), then AWS SNS will attempt again to send multiple requests to my server, which means that my app will eventually end up processing multiple requests for one single task. – user1370897 Sep 12 '15 at 23:54

1 Answers1

0

I ended up fixing this issue by getting the session from the incoming request and storing it to a local variable in my action controller, then made sure the session got activated or started:

use Symfony\Component\HttpFoundation\Request;

public function myFunctionAction(Request $request) {
   $session = $request->getSession();
   $session->start();

next, I immediately sent the response and headers to the client:

    ob_start();
    $response = new Response('Status: OK', 200);
    echo $response; // send the response
    header('Connection: close');
    header('Content-Length: ' . ob_get_length());
    ob_end_flush();
    if (ob_get_level() > 0) {
        ob_flush();
    }
    flush();

Then the code continues doing the heavy work as usual. The key to solving this issue was, however, to make sure that the service that utilizes Session to provide the option to others who will be referencing it to save or not save the session within the service. If the session gets saved then it won't be active anymore and it gets closed, and once it is closed you cannot start it again since headers were already sent. The client code that references the service should however save and close the session in the end of course.

I ended up not listening for the kernel.terminate event since there was no need for it in my case.

user1370897
  • 503
  • 8
  • 15