I'm trying to create a simple Web service that has to return various HTTP codes depending on some conditions, mainly the existence of files related to the specific resources requested via URI. However, i'm stuck on a really strange behaviour i keep getting when I try to generate a 404 header via PHP.
The first snippet, that works, is as follows:
$isNotFound = TRUE;
if ($isNotFound) header('HTTP/1.1 404 Not Found');
Using a simple command-line cURL to request the URI behind which this script runs, I get:
$ curl -LI http://www.example.com/
HTTP/1.1 404 Not Found
Date: Wed, 18 Sep 2013 20:57.25 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.8
Vary: Accept-Encoding
Connection: clse
Content-Type: text/html
Now, the second take is like this:
$isNotFound = FALSE;
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$isNotFound = TRUE;
}
if ($isNotFound === TRUE) {
header('HTTP/1.1 404 Not Found');
}
Running cURL again, this time I get this:
$ curl -LI http://www.example.com/
HTTP/1.1 200 OK
Date: ...
The header is the same as the former, except for the code. To check the obvious, I also printed the value of $isNotFound just before the last if, and it was indeed evaluated to TRUE, so the header call with the 404 code should be executed. I also added an exit() inside the last if, and another header() at the end of the script, giving other codes in response (like 302), and the result is always that the header inside the if is ignored.
I managed to make the second script work by explicitly specifying the request method as GET in the cURL call:
$ curl -X GET -LI http://www.example.com/
HTTP/1.1 404 Not Found
Date: ...
I also had the doubt that cURL wasn't using GET as the default method, but printing the $_SERVER array showed that the request method was indeed GET.
So, what is the reason of this strange behaviour? Is cURL's fault when using the implicit GET method, or is something happening inside PHP? Or maybe i'm so tired that i'm missing something trivial?
Thank you guys, and sorry for the long post.
Next time read the manual:
-I, --head
(HTTP/FTP/FILE) Fetch the HTTP-header only! HTTP-servers feature the
command HEAD which this uses to get nothing but the header of a
document. When used on an FTP or FILE file, curl displays the
file size and last modification time only.
(or your webserver log files, or your TCP stream)
Related
So basically I am trying to send data to a textfile in raspberrypi(apache server) from my ESP01 using AT-Commands.
I am trying to use POST method of apache for same.
Here is my PHP code:
`<?php
$tempF=$_POST["temp"];
$file='testfile.text';
$myfile=($file,"w+");
fwrite($myfile,$tempF);
fclose($myfile);
?>`
Here is the data I send through AT Command (AT+CIPSEND)
`POST /TEMP/post.php HTTP/1.1\r\nHost: 192.168.0.138:80\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length:9 \r\n\r\ntemp=1234`
So when I send this AT command, I assume that php file should be executed and data from 'temp' variable should be written to the text file. However there is no such output visible nor any errors displayed.
Here is simple map of how paths are placed
root folder:/var/www/html
inside it -> TEMP(folder), index.html
inside TEMP -> post.php, testfile.txt
I have already tried following :
Replace the $tempF variable with text and execute PHP on raspberrypi. So I conclude that there is no issue in php code since it worked great.
Enabled php mod and simple php index file works too.
3)Tried changing all possible pathways.
4)Give complete permissions to all files to read, write and execute in root folder. i.e index.html, post.php and testfile.txt
Screenshot of my at commands
P.S.
I am new to PHP and POST method of HTTP/1.1
Thanks☻
EDIT 1: As from Juraj's comment I realised that when you send \r\n through serial monitor it actually sends \n and so I tried the conventional method while entering Post Command as follows:
POST /TEMP/post.php HTTP/1.1
Host: 192.168.0.138:80
Content-Type: application/x-www-form-urlencoded
Content-Length:9
temp=1234
And I recieved following Error:
+IPD,187:HTTP/1.0 500 Internal Server Error
Date: Fri, 06 Aug 2021 13:06:57 GMT
Server: Apache/2.4.38 (Raspbian)
Content-Length: 0
Connection: close
Content-Type: text/html; charset=UTF-8
Update:
While searching for same, I found reqbin.com which helps to test POST/GET methods too and I still got same error 500.
Note:My timeout currently is 120000ms and all files are given full permissions.
I Send Data to a webserver with POST or PUT method (server is FreeBSD, Apache httpd, php72).
I want to detect a 413 (too large) in my PHP script. But var_dump(http_response_code()); gives 200 even i uploaded data was too large (Apache httpd answers with it's 413 page, and my script gets executed as well).
var_dump($_SERVER); does also not show anything with 413.
How can i detect http status like 413 or any other in my script? and is it possible to let my script output the error-message, not apache?
my php-script looks like this
<?php
header('Content-Type: application/octet-stream');
echo ">---- output from php-script begins here\n";
if (http_response_code() != 200) { # <---- this does not work, always 200, how to detect http status code 413 from apache httpd?
echo ">---- not ok\n";
}
else {
echo ">---- ok\n";
}
?>
i use this command to upload a file
curl --head --silent --show-error --upload-file test-big-file.txt "my-domain.com/upload.php"
HTTP/1.1 413 Request Entity Too Large
Date: Thu, 09 Apr 2020 12:08:46 GMT
Server: Apache
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>413 Request Entity Too Large</title>
</head><body>
<h1>Request Entity Too Large</h1>
The requested resource does not allow request data with PUT requests, or the amount of data provided in
the request exceeds the capacity limit.
</body></html>
>---- output from php-script begins here
>---- ok
it does not make much sense to me that apache is prepending some error-message to my php-script-output. either user should get an error message or the output of my script. but not both at the same time.
if i clould detect this 413 in php i could just output some meaningful message and exit the script.
SOLUTION
i found out that if i use https:// for uploading the file apache does not call my php-script if file was too big.
only if i use http:// apache does this strange thing showing the error-document AND executing the php-script. i have absolutly no clue why this is. however... because i want to use https anyways... problem for me is gone.
here is an example output to see the diffrence in http and https in my case (CustomErrorDocument is emtpy, so no error output besides the header is shown here, in the final version, there will be an error-document of course)
curl --head --silent --show-error --upload-file test-big-file.txt "https://my-domain.com/test.php"
HTTP/2 413
date: Thu, 09 Apr 2020 17:22:23 GMT
server: Apache
content-type: text/html; charset=UTF-8
curl --head --silent --show-error --upload-file test-big-file.txt "http://my-domain.com/test.php"
HTTP/1.1 413 Request Entity Too Large
Date: Thu, 09 Apr 2020 17:22:28 GMT
Server: Apache
Upgrade: h2,h2c
Connection: Upgrade, close
Content-Type: text/html; charset=UTF-8
--> here is the output of the script that should not be executed <--
the line "--> here is the output of the script that should not be executed <--" is missing in the https call... it's only present in http call. strange...
notice: use of https gets an HTTP/2 response instead of HTTP/1.1
however, must be a misconfiguration from my web-hoster or a bug in HTTP/1.1 processing in apache. so problem solved by forcing everything to HTTPS
and usage of ErrorDocument in .htacces to show own document on error as suggested by #ÁlvaroGonzález fixed it for me (users trying to use http will get an 301 Moved Permanently error with correct https-link). works for me.
thanks
PHP's $_SERVER['HTTP_IF_NONE_MATCH'] is always empty however Firefox's Web Developer Network Requests tab shows the request header as being If-Modified-Since: "Tue, 27 Jun 2017 09:08:23 GMT". Cache is not disabled and my .htaccess file contains the following:
RewriteEngine on
RewriteRule .* - [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}]
How do I get PHP's $_SERVER['HTTP_IF_NONE_MATCH'] to return the request header properly or how do I access that request header in an alternative manner? I came across getenv('HTTP_IF_MODIFIED_SINCE') though that didn't return anything either. Is it possible there is something in the php.ini file that needs to be changed? It is a fairly fresh server setup.
You should add a If-None-Match http header to your server. If you do so the HTTP_IF_NONE_MATCH server variable should contain the value of the set If-None-Match header.
curl http://my/endpoint --header 'If-None-Match: "my-custom-etag-value"'
Background
Part of my application's responsibility is handling requests for static resources (CSS, JavaScript, images) in a controlled manner. Based on some application logic, it will return one from a selection of different files that might be served on that URL at different times and to different users. These are therefore static files, but delivered in a dynamic way.
The application is based on Symfony Components and the serving of these static-ish files is handled by the BinaryFileResponse class.
The bootstrap code calls the trustXSendfileTypeHeader method:
\Symfony\Component\HttpFoundation\BinaryFileResponse::trustXSendfileTypeHeader();
The application uses some internal logic based on configuration and the detection and use of apache_get_modules() to determine availability. If XSendfile is available and the configuration says to use it, it sets the X-Sendfile-Type header:
if ($useHeader === true) {
$request->headers->set('X-Sendfile-Type', $header);
}
$response = new BinaryFileResponse($filename);
Problem
When I run this with the configuration set to never use XSendfile, or through the PHP built-in web server, which obviously does not support XSendfile, everything is perfect.
When I utilise XSendfile, it also works -- most of the time.
Every so often, typically if I press the f5 key 3-4 times in quick succession, "something" wigs out and I get a garbled response. For example, this is supposed to be a JavaScript file (copied from "Response" tab under "Net" in Firebug):
hxYîãx��HTTP/1.1 200 OK Date: Tue, 05 Feb 2013 14:49:10 GMT Server:
Apache/2.2.22 (Ubuntu) X-Powered-By: PHP/5.4.6-1ubuntu1.1
Cache-Control: public Last-Modified: Tue, 29 Jan 2013 13:33:23 GMT
Accept-Ranges: bytes Content-Transfer-Encoding: binary ETag:
"10426f-9f6-0" Vary: Accept-Encoding Content-Encoding: gzip
Content-Length: 1011 Keep-Alive: timeout=5, max=98 Connection:
Keep-Alive Content-Type: application/javascript
������VmoÛ6þ,ÿkÀ²ãIý°~q [Üt]
XÑt¶H¤#Rv¼Àÿ}w(YSÀØ2yïå¹*¾Á>¯¥¥,è) Æ^Ât¸BaÆ\éjgäjí
Î&ð*¸Åí¸tY!³Ç$Óe"jÞ![#,n®®oï®A¨þ¸þù××Þ©¼¼ôÇêÚd¹49mv°ÔrtBÖ^;WÍÓÔg´Y¥´FéôÁR9o°35Îà^º´N=UÐèEµ¢XE¸íÒ%ª°¨Úò7¬KñT¾{;£ÈrTnß³étUè{QÀçÍn·:'üJëQÍÄËZeNjOàyÕÁ:#3wö~4Òét1ù$µeN)RD|
¶FTØJ·ß½¥¨¸õGç >9TyÜxzgl-J:) b«9ûAQ½KXÉ!yÐÓ]
óÆÎ#W¡?¢vún·7j©ÿ¢ðõÖGEÁy\ºp¤÷cKxf?ï*¼Éç0^ïîÌÇ°ñDQ¸mYJ|4t¾ñæËÛ¯Å
¨6:çøp(}þÑò|LÂ;Õ(#v¹* /[¨U|xª
æ]ÍyìjµòÛ¯p?4sI¥"v÷ôp|uQ4ò4&Ï·$eÒc¸ xo%7Ôi´2ñx;TuÙj23 áÊ%ħ¿¹lÌwÀS.&ÏØß7¸}ó
ZXzå k2'Zdùè
�¦ºû-Ù[Ó²ÿU(¯¤¥=pÃjô¾ç]]Øhhô²×ÙãÚÍ4¨[!Õ}'Òþ^Ð�ûxÿ#+ÚVÞ~áÌáy?d
aíD¹·U×ÃÚ] õ5íÃø¨o÷ÂAvUÆmÍaày`¦ä©A?mL[-}®(ÿË
d°öò¬}Ç¢³Çp1À^6%0 hTô^ts´ÞíWô
fO¶ö¢ÎNÜæ·HîUôÔ¶±ÌCµsxh.9åçi Û·_ÈÞØ_ÄãY_Ö}G<ì°ý2wÔ¿aw8/þù\ã±þ"0C
oÂh'tE¶À¤¥7I½éßRt.s?á^d|k/Æ)wRw÷cG¿<Þ
¼´°/^ø*ʤAVZ×y¿zÅΪ¥[²Õ1ò_Vµæï_YXÁÕö ��YXÁÕö ��
Note the presence of the headers in the response body, and the rest of it which is clearly not JavaScript. There are also some spurious characters at the start, which possibly is what leads to the headers being pushed to the body. I have tried to determine if this content is the result of gzipping, but I can't confirm that yet. (See also update below)
Question
Firstly, is BinaryFileResponse even the correct class to use for serving text (non-binary) files? The documentation for the class only says "BinaryFileResponse represents an HTTP response delivering a file." This isn't very detailed but it doesn't say anything about it being exclusively for "binary" files. However the name has its own implications, why didn't Fabien just call this class FileResponse?
Secondly, and more importantly, what could be causing this? I don't believe it is a browser issue because it is repeatable in both Firefox and Chrome. Is this a bug in the XSendfile module or in the BinaryFileResponse class perhaps? (I am likely to think it is not the former because I have used it before in a more "raw" way not via Symfony Components, with no such issues).
Has anyone else experienced this? Any idea where I should even start looking to track this down? I've looked at the BinaryResponseFile source code but it doesn't really do much with XSendfile, just sets the relevant header and prevents content in the response body, from what I can see.
Update
I've just noticed a couple of things about these garbled responses:
There are no actual headers being sent at all, i.e. on the "Headers" tab in Firebug, for the garbled responses, it only lists Request headers and doesn't even show the heading for Response headers.
Even if I set some custom header on the Response in PHP, that header does not appear at all in the garbled responses (as a header or in the response body), but the custom headers appear correctly for the responses that aren't broken.
First, let me say that I don't have any experience with this Apache module, but I'll try to guide you through a general error deduction:
You should check if you can reproduce it more reliably. While a web browser might be ok to try it out, you should go for something like curl and do the request multiple times, for example using a bash for-loop.
for i in `seq 1 5`; do curl -v http://localhost/xsendfile-url; done
The fact that the Connection: Keep-Alive header is set and that there are some weird characters before the actual HTTP header lead me to believe that you won't be able to reproduce this problem with separated curl calls, because it will open a fresh connection each time. So try this to check if that gives you the weird behavior (curl has keep alive on by default):
curl -v http://localhost/xsendfile-url http://localhost/xsendfile-url http://localhost/xsendfile-url
Using this, you could go to the projects github issue page and report your findings. Most probably they will there help you in telling you why mod_xsendfile is behaving the way it is or that you have found a bug.
I'm trying to stream an ipcamera through PHP using the following code;
<?
# Stop apache timing out
set_time_limit(0);
# Set the correct header
header('Content-Type: multipart/x-mixed-replace;boundary=ipcamera');
# Read the images
readfile('http://[USER]:[PASSWORD]#[IPADDRESS]:[PORT]/videostream.cgi');
?>
This script works just fine on my localhost running apache and php, however on my web server (tested on 2 servers), I receive a 400 Bad Request error. I was previously receiving a 'connection refused' error, but this was resolved by my host forwarding the correct port.
Is 400 not something like incorrect syntax? Could this be because i have the "[USER]:[PASSWORD]#" in the url? If so, is there another way I can authenticate before running readfile?
I have run the following cases to determine the response code;
readfile('http://[USER]:[PASSWORD]#[IPADDRESS]:[PORT]/NONEXISTINGFILE.cgi');
// Returns 400 Bad Request (Should be 404)
readfile('http://[IPADDRESS]:[PORT]/NONEXISTINGFILE.cgi');
// Returns 404 Not Found (Correct Response)
readfile('http://[IPADDRESS]:[PORT]/videostream.cgi');
// Returns 401 Unauthorized (Correct Response)
readfile('http://[USER]:[PASSWORD]#[IPADDRESS]:[PORT]/videostream.cgi');
// Returns 400 Bad Request (Incorrect - Should be .. 200(?) OK)
readfile('http://[USER]:[PASSWORD]#[IPADDRESS]:[PORT]/FILETHATDOESEXIST.jpg');
// Returns 400 Bad Request (Should be 200(?) OK)
readfile('http://[IPADDRESS]:[PORT]/FILETHATDOESEXIST.jpg');
// Returns 200(?) OK (Correct Response)
If someone is able to give me the curl equivalent of this script, perhaps this is the solution. The Bounty still stands to anyone who can solve this for me :)
Regards,
For curl, try something like:
<?php
# Stop apache timing out
set_time_limit(0);
# Set the correct header
header('Content-Type: multipart/x-mixed-replace;boundary=ipcamera');
# Read the images
$ch = curl_init('http://[IPADDRESS]:[PORT]/videostream.cgi');
curl_setopt($ch, CURLOPT_USERPWD, '[USER]:[PASSWORD]');
curl_exec($ch);
If you want to continue to use readfile(), you could use stream_context_create() to construct a stream context for readfile. See this documentation on php.net to see how that could be done - specifically, you will want to create an HTTP stream context that passes an Authentication header.
simply check your [USER] and [PASSWORD] ... make sure it does not contains :, /, # ...
if there is escape it with \
You might have something set in your PHP.INI on the production server that is disabling readfile's ability to load external URLs.
I'm specifically thinking about allow_url_fopen which may be set to FALSE, though it may be something else.
You can also check you web server's error log for clues. PHP will usually emit a specific warning.