PHP Connection: Close - php

I have a PHP application that I have been having some problems with, some pages take a very long time to load.
After a couple of hours I have figured out the problem, but I have no idea how to fix it.
The problem seems to be with the header Connection: keep-alive. I used a Firefox plugin called "Tamper Data" which allows you to "tamper" with the headers and stuff. Once I used that tool to change the connection header to Connection: close the delay on some pages stopped.
How, in PHP, can I make sure that the Connection: close header is used?
I tried putting header("Connection: close"); at the top of a PHP file, and reloaded the page. It still sends the Connection: keep-alive header, not the one I am trying to send.
How can I achieve what I am trying to do?
EDIT: I have just realized that on this subdomain the content-length header is not sent at all for most pages. It is only sent right after a form submission followed by a redirect.
EDIT 2:
This is the page: http://volunteer.essentialtransit.com/job/13/just-a-test-at-eta/
Click the "Apply now" link and fill out some random txt, you don't need to attach a file. Notice when you are redirected back to the "job" detail page that it will take a very long time to load.

Your problem has nothing to do with connection states. It might seem related to connections because Apache automatically spawns a new child thread for each new request originating from a different source. With keep-alive, it will attempt to reuse the previous thread, which is busy from a PHP script (from your application). It's a little more complicated actually but this is the basic. Just note that "Connection: Close" is being sent, but it's supposed to close the connection only after the script has finished (sent all buffers out).
Now I'm going to tell you how to debug your script. I'll do this because if you don't fix your problem and you gain more traffic, your host will kick you out for extreme resource usage.
So:
Append set_time_limit(5) or higher to confirm there's a background script problem
Check for requests to local resources, requests that would only work on your staging server (you can use WireShark for this)
Check for external requests, cURL, file_get_contents() calls, anything with a timeout
Benchmark and optimize lengthy scripts (you can try xdebug for this)
Log all PHP notices, warnings and errors to a file; you should get at most zero errors
Finally, it's a good practice to triple-check your entire application. One for data entry, second for data operations and third for modules interconnection. But you should focus on AJAX background scripts that can't return output
Of course, skip anything that doesn't apply.

So, I determined what the problem was, and found a work-around to this issue.
The script that processed the form just processed the input and redirected to another page, but it actually didn't output anything. On most pages on the site the content-length header is either not sent, or is set at the correct value. But for some reason when posting to a page, and then redirecting without the processing script outputting anything to the browser, the content-length was being set at 0.
I tried setting the content-length myself, but didn't have much luck, as it didn't seem to make a difference.
So, all I did was make the processing script have some output. So now when the form is submitted the processing script outputs a page with a redirect script (and a 'click to continue' message just in case) that leads to the correct page. So while this adds a very brief delay between the form submission and the correct page being seen it causes the content-length to be set correctly and the problem is solved.
While this is not an ideal solution it is manageable and makes the script work.

Related

Is it possible to access an html document from a different PHP script than the one that generated it?

Here is the scenario:
I have a page that is logging data to MYSQL. I have another page that reads that data and allows it to be viewed. When a new piece of data is logged I would like to have the first script check and see if the viewing page is open in the browser, and if so append the newest data to the end of the view. Also - could anyone point to some info giving an overview of how PHP and the browser interact? I think I have the concept of the DOM down for javascript...but as far as PHP it just appears that once the page is sent, that's it...
You're correct in that once the PHP is sent, that's it.
There is no way to send data to a PHP page once the page is loaded. There is another slightly nastier method, but the easiest way of doing this is going to be polling the page via Ajax.
So, have a script that every 20 seconds, sends a message to another PHP script that contains the timestamp of the last MySQL log you received, then get the script to return all the data that has been set by that time.
I'm unsure how new you are to JavaScript, but the easiest way of doing that is probably using JQuery's $.ajax and encoding the new MySQL records as JSON.
No this isn't possible as you describe. The viewing page will have to poll the server for changes, either by periodically reloading itself, or by javascript / AJAX.
You are right that once the page is sent by PHP it can have no further influence. In fact the PHP execution thread on the server is killed as soon as output is complete, so the thing that generated the page no longer even exists.
To expand on Dolondro's suggestion, rather than periodically polling the server for updates, you could use Server-Sent-Events (newly supported in modern browsers).
With these, you basically just send 1 ajax request to the server, and the connection is held open. Then, the server can send updates whenever it wants. When the browser receives an event, it can add the data to the screen. Even still, the connection is held open, and the server can send additional events/updates as they occur.
W3C page:
http://dev.w3.org/html5/eventsource/
Wikipedia:
http://en.wikipedia.org/wiki/Server-sent_events
More Info:
https://www.google.com/search?ix=hcb&sourceid=chrome&ie=UTF-8&q=server+sent+events

Uncontrolled multiple page reloading?

I notoced a strage behaviour at one of the websites I work on: trying to make an insert intro the database I saw that there were being inserted more than one(as I was expecting) row. After some attempts of indentifying the problem I made a test by creating a session variable (an array) in the index.php an pushed one value. At the first load of the page the session array printed one value, but on the next reloads it printed 6 values a time.
I mention that i had a .htaccess file, wich I suspected, but now it is empty, so it shouldn't be the problem.
Did anyone get this strange behavior? How can I fix it?
Thx!
You can always have full control of any page reload.
Just keep an eye on the HTTP interchange while querying your server.
Use either Fiddler HTTP proxy or Firebug or any other addon with HTTP sniffer capability.
So, you will see every HTTP request your browser do as well as every HTTP response your server returns.

How to stop the 1st ajax request if it is called again before the first call gets a response?

There might be some cases that your request takes long time because
of some problems with your client internet connection or your server
connection. So since the client doesn't want to wait he clicks on the Ajax
link again which sends the request to the server again which messes up
the following:
Rendering of our website in the browser because we are giving extra
load to the browser.
What if the second request processed correctly and you showed user
the page and then comes along the error message from your first
request(saying request timed out) which loads above on the correct
content and mess up with the user reading the correct content.
I want to stop the 1st Ajax response if the Ajax function is called twice. How do I do this?
so i want to stop the 1st Ajax response if the Ajax function is called
twice
What you actually want is to prevent a second request when a first request is in progress.
For example, You may have to change the Save button to Saving..., disable it (and add a little progress wheel) to give live feedback to the user. (Facebook does this)
The key is love feedback to the user. If the user is clueless on what is going on, they are going to think nothing is happening.
You might want to check why the operation is taking long
If this is a complex/time consuming operation, like, say a report generation or a file upload, a progress bar should do
If this is because of the client's internet connection, say it up front, like Gmail: Your have a slow Internet connection and this site may be slow. Better still, provide a fallback option, with less/no Ajax.
You say cause we are giving extra load to the browser: this is kind of fishy. You will not be giving extra load to the browser unless you are giving it tons of HTML to render. Use Ajax only for small updates on the browser. You may want to reload the page if you expect a large change.
How bout seeing as your using some form of JavaScript to begin with you have that link either hidden or disabled in a manor of speaking til the pages request has been followed through with. You could for example have the requested ajax wait for a second variable that would enable that link so a user could click it. But until that variable is received from the original AJAX request its disabled to the click, then if it is clicked it disables again and waits for the same variable to come back again.
Think of how some developers disable a submit button on a form so a user can't double submit there form.. same concept of notion here.

Do dynamic web pages always contain content-length field in HTTP header?

Do dynamic pages like CGI, PHP, ASP, SSI always contain content-length field in the HTTP headers. If not why? Please provide links to webpages hosted on servers which don't include the Content-Length field in the headers. I want to see it first hand.
Per RFC 2616:
In HTTP, it SHOULD be sent whenever
the message's length can be determined
prior to being transferred,
It is often the case that the length cannot be determined beforehand. If you want to check out headers, try curl -I http://www.example.com. You'll quickly see that some sites do and some sites don't.
I think that pages NOT need always to send their content-length.
From the browser side, if browser knows the content-length can show the loading bar, or else just wait to see the "end of the file". If you send a file is better to sent the content-length or else user can not see this loading bar and can't be sure that the file is fully loaded. But if you just have a page, the browser just load until gets the end.
The reason is that some pages can create their content while they send their data on the client. This way user no need to wait too much to see the first data coming.
This Dogs page is an example. Also amazon did not send the content-length on most page for the same reason.
The page is flush the data after find the first item, and then is flush the data time to time, so the user not need to spend time waiting for the program first find them all, then calculate the size of the page, and then start sending the data.

redirect user, then log his visit using php and mysql

I have a PHP redirect page to track clicks on links. Basically it does:
- get url from $_GET
- connect to database
- create row for url, or update with 1 hit if it exists
- redirect browser to url using Location: header
I was wondering if it's possible to send the redirect to the client first, so it can get on with it's job, and then log the click. Would simply switching things around work?
You can do this:
get url from $_GET
send Location: header
call flush()
connect to database
create row for url, or update with 1 hit if it exists
This will not necessarily cause the browser to go on its way immediately, since your connection is still being held open and what the browser does about that is up to it, but (barring conditions that cause flush() to not work) it will at least get the Location: header out to the browser so it can do the redirect if it likes.
If that's not good enough, I'd recommend dumping your data to per-minute or per-second files that a script then picks up for postprocessing into the database. If that's not good enough, you can play with pcntl_fork(); this is an extremely hairy thing to do under Apache SAPI.
Most databases give you the ability to insert a query delayed, so it'll only process when the database is idle. You're most likely best doing that...so long as the data isn't critical (you'll lose the query if mysqld dies or the RAM is flushed).
http://dev.mysql.com/doc/refman/5.1/en/insert-delayed.html
That is fine. PHP will finish executing before flushing the redirect header to the client. If you still have doubts try saving this in a file and loading from browser:
<?php
header('location: /');
sleep(2);
?>
The redirect should not happen for 2 seconds.

Categories