Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I close a connection early?

Tags:

jquery

ajax

php

I'm attempting to do an AJAX call (via JQuery) that will initiate a fairly long process. I'd like the script to simply send a response indicating that the process has started, but JQuery won't return the response until the PHP script is done running.

I've tried this with a "close" header (below), and also with output buffering; neither seems to work. Any guesses? or is this something I need to do in JQuery?

<?php  echo( "We'll email you as soon as this is done." );  header( "Connection: Close" );  // do some stuff that will take a while  mail( '[email protected]', "okay I'm done", 'Yup, all done.' );  ?> 
like image 561
Eric_WVGG Avatar asked Sep 26 '08 09:09

Eric_WVGG


People also ask

What does Conn close () do?

Closes the connection to the database.

What does close connection mean?

HTTP/1.1 defines the "close" connection option for the sender to. signal that the connection will be closed after completion of the. response. For example, Connection: close. in either the request or the response header fields indicates that the connection SHOULD NOT be considered `persistent' (section 8.1)

When to close http connection?

In HTTP 1.0, the server always closes the connection after sending the response UNLESS the client sent a Connection: keep-alive request header and the server sent a Connection: keep-alive response header. If no such response header exists, the client must close its end of the connection after receiving the response.

Can server close TCP connection?

Any HTTP client, server, or proxy can close a TCP transport connection at any time. The connections normally are closed at the end of a message, but during error conditions, the connection may be closed in the middle of a header line or in other strange places.


2 Answers

The following PHP manual page (incl. user-notes) suggests multiple instructions on how to close the TCP connection to the browser without ending the PHP script:

  • Connection handling Docs

Supposedly it requires a bit more than sending a close header.


OP then confirms: yup, this did the trick: pointing to user-note #71172 (Nov 2006) copied here:

Closing the users browser connection whilst keeping your php script running has been an issue since [PHP] 4.1, when the behaviour of register_shutdown_function() was modified so that it would not automatically close the users connection.

sts at mail dot xubion dot hu Posted the original solution:

<?php header("Connection: close"); ob_start(); phpinfo(); $size = ob_get_length(); header("Content-Length: $size"); ob_end_flush(); flush(); sleep(13); error_log("do something in the background"); ?> 

Which works fine until you substitute phpinfo() for echo('text I want user to see'); in which case the headers are never sent!

The solution is to explicitly turn off output buffering and clear the buffer prior to sending your header information. Example:

<?php ob_end_clean(); header("Connection: close"); ignore_user_abort(true); // just to be safe ob_start(); echo('Text the user will see'); $size = ob_get_length(); header("Content-Length: $size"); ob_end_flush(); // Strange behaviour, will not work flush(); // Unless both are called ! // Do processing here  sleep(30); echo('Text user will never see'); ?> 

Just spent 3 hours trying to figure this one out, hope it helps someone :)

Tested in:

  • IE 7.5730.11
  • Mozilla Firefox 1.81

Later on in July 2010 in a related answer Arctic Fire then linked two further user-notes that were-follow-ups to the one above:

  • Connection Handling user-note #89177 (Feb 2009)
  • Connection Handling user-note #93441 (Sep 2009)
like image 173
Joeri Sebrechts Avatar answered Sep 20 '22 11:09

Joeri Sebrechts


It's necessary to send these 2 headers:

Connection: close Content-Length: n (n = size of output in bytes ) 

Since you need know the size of your output, you'll need to buffer your output, then flush it to the browser:

// buffer all upcoming output ob_start(); echo 'We\'ll email you as soon as this is done.';  // get the size of the output $size = ob_get_length();  // send headers to tell the browser to close the connection header('Content-Length: '.$size); header('Connection: close');  // flush all output ob_end_flush(); ob_flush(); flush();  // if you're using sessions, this prevents subsequent requests // from hanging while the background process executes if (session_id()) {session_write_close();}  /******** background process starts here ********/ 

Also, if your web server is using automatic gzip compression on the output (ie. Apache with mod_deflate), this won't work because actual size of the output is changed, and the Content-Length is no longer accurate. Disable gzip compression the particular script.

For more details, visit http://www.zulius.com/how-to/close-browser-connection-continue-execution

like image 36
Timbo White Avatar answered Sep 19 '22 11:09

Timbo White