Progress bar: WordPress AJAX and HTTP Headers (ERR_RESPONSE_HEADERS_TOO_BIG)

This is a quick note that explains a gotcha with regards to creating a progress bar or similar.  I’m writing code for WordPress but this strongly related to PHP, SESSION, AJAX and web browsers.

I wanted to use _SESSION to record progress in a loop which in concept looks like:

 session_start();
 foreach ($json['rows'] as $computer) {
   usleep(1000);
   $_SESSION['DMUPCASyncComputersCode']++;
 }

I had read that parallel AJAX calls might fail if used with PHP’s _SESSION because sessions block.  I thought storing the same information in a database would use a lot of resource which I want to avoid and so I thought I might be able free the block.  The code became:

 foreach ($json['rows'] as $division) {
   session_start();
   usleep(1000);
   $_SESSION['DMUPCASyncDivisionsCode']++;
   session_write_close();
 }

This was working great for a short loop but fails against longer loops.  Firefox was returning: xhr.status 0 which meant that my AJAX call would not finish and cancel the timer firing the progress check.  When you search for “ajax xhr.status 0” some reasonable fixes come up.  I think my code is better because of them but they didn’t fix this error.

When I ran this under Chrome I ran in to the same issue but the Javascript console kicked up: net::ERR_RESPONSE_HEADERS_TOO_BIG and bingo! had something else to chase.  In my Docker container running a LAMP stack with WordPress, I ran ngrep in order to see what headers were being sent and the culprit was there loud and proud:

..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; pat
 h=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; 
 path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c
 7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d
 66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432
 d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1
 432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d3
 2c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc
 1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a37504
 1bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a37
 5041bc1d32c1432d3d66c7; path=/..Set-Cookie: PHPSESSID=2292e08a375041bc1d32c1432d3d66c7;

Every time a session_start() is called a cookie is written to the output.  I thought I was defeated and a database solution was the proper route (it may still be…).  However, I found header_remove(‘Set-Cookie’); which if called before EVERY session_start(); it strips the “Set-Cookie” pragmas from the header.  The code now looks a bit like this:

 foreach ($json['rows'] as $computer) {
   header_remove('Set-Cookie');
   session_start();
   usleep(1000);
   $_SESSION['DMUPCASyncComputersCode']++;
   session_write_close();
 }

I hope this helps you so that you don’t have to bruise your head against a wall like I did.

 

About c3iq

Free(dom) software, GNU/Linux, Fish, Family
This entry was posted in Development and tagged , , , , , . Bookmark the permalink.