I am facing a problem when a remote web client with slow connection fails to send complete POST request with multipart/form-data
content but PHP still uses partially received data to populate $_POST
array. As a result one value in $_POST
array can be incomplete and more values can be missing. I tried to ask same question in Apache list first and got an answer that Apache doesn't buffer the request body and passes it to PHP module as a
giant blob.
Here is my sample POST request:
POST /test.php HTTP/1.0
Connection: close
Content-Length: 10000
Content-Type: multipart/form-data; boundary=ABCDEF
--ABCDEF
Content-Disposition: form-data; name="a"
A
--ABCDEF
You can see that Content-Length
is 10000
bytes, but I send just one var a=A
.
The PHP script is:
<?php print_r($_REQUEST); ?>
Web server waits for about 10 seconds for the rest of my request (but I don't send anything) and then returns this response:
HTTP/1.1 200 OK
Date: Wed, 27 Nov 2013 19:42:20 GMT
Server: Apache/2.2.22 (Debian)
X-Powered-By: PHP/5.4.4-14+deb7u3
Vary: Accept-Encoding
Content-Length: 23
Connection: close
Content-Type: text/html
Array
(
[a] => A
)
So here is my question: How can I verify in PHP that the post request was received completely? $_SERVER['CONTENT_LENGTH']
would show 10000
from the request header, but is there a way to check the real content length received?
They probably get cutoff by limits in Apache or PHP. I believe Apache also has a config variable for this.
Here are the PHP settings;
php.ini
.htaccess
maybe you can check with a valid variable, but not length, eg:
You can add field
<input type="hidden" name="complete">
(for example) as the last parameter. inPHP
check firstly whether this parameter was sent from client. if this parameter sent - you can be sure that you got the entire data.Now, i'm not sure that the order of parameters must be preserved according the RFC (of both, HTML and HTTP). but i've tried some variations and i saw that the order kept indeed.
Better solution will be, calculate (on client side) hash of the parameters and send him as another parameter. so you can be absolutely sure that you got the entire data. But this is starting to sound complicated...
I think what you are looking for is $HTTP_RAW_POST_DATA, this will give you the real POST length and then you can compare it to $_SERVER['CONTENT_LENGTH'].
This is a known bug in PHP and needs to be fixed there - https://bugs.php.net/bug.php?id=61471
If you can change the enctype to
the you can check
vs.