I'm new to development and I'm trying to learn php.
Why is it that when I use the code below, the redirection, (through the header syntax), is still taking place even though content has been output before it ?
<html>
<body>
<p>My Page</p>
</body>
</html>
<?php
$redirect_page = 'http://localhost';
$redirect = true;
echo "Some Text";
if($redirect==true){
header('Location: '.$redirect_page);
}
?>
Many thanks in advance
HTTP requires response headers to arrive strictly before the body content, like so:
HTTP/1.1 200 OK
Powered-By: PHP/7.0.0-20150527
Content-Type: text/html; charset=utf-8
<html><body>Hello world!</body></html>
For PHP to comply with that requirement, PHP must send all accumulated headers at the instant it's ready to send any body content. The answer to your question hinges on the definition of when PHP is "ready to send".
To figure that out, look at your output_buffering setting:
var_dump(ini_get('output_buffering'));
On my machine with default settings, that returns 4096, which according to the manual means that PHP will be "ready to send" when 4096 body bytes have been accumulated.
To get the page to behave as you expect (ie, not sending the headers), you need to output enough bytes to exceed the setting of output_buffering. You can either do that by reducing the output buffering setting or by emitting more body text, eg:
echo str_repeat('<div/>', 4096);
See also this SO primer.
Related
I have a PHP script that serves portions of a PDF file by byte ranges.
If an HTTP HEAD request is received, it should send back headers (including the PDF file size) but not the actual file contents. I have tried this:
header('HTTP/1.1 200 OK');
header('Content-Type: application/pdf');
header('Accept-Ranges: bytes');
header('Content-Length: '.filesize($Pathname));
die;
The problem is that something (I assume the web server == LiteSpeed) replaces the Content-Length header with Content-Length: 0 - which defeats the whole purpose.
Can anyone suggest what I should be doing? Thanks
From w3c Hypertext Transfer Protocol -- HTTP/1.1:
When a Content-Length is given in a message where a message-body is
allowed, its field value MUST exactly match the number of OCTETs in
the message-body. HTTP/1.1 user agents MUST notify the user when an
invalid length is received and detected.
And:
The Content-Length entity-header field indicates the size of the
entity-body, in decimal number of OCTETs, sent to the recipient or, in
the case of the HEAD method, the size of the entity-body that would
have been sent had the request been a GET.
So, I suppose, your code will properly work if you send real HEAD request to your server.
It's the webserver job, not yours.
In my case I left everything to the Apache webserver and nothing changed in my php code except of how the requests is being parsed
For example things like
if($_SERVER['REQUEST_METHOD'] === "GET"){
//ok
}else{
//send 400 Bad Request
}
are changed to
if($_SERVER['REQUEST_METHOD'] === "GET" || $_SERVER['REQUEST_METHOD'] === "HEAD"){
//ok
}else{
//send 400 Bad Request
}
and Apache did all the heavy lifting (striped the response body).
(don't try to ob_clean() or die("") or things like this).
related resources:
http://hc.apache.org/httpclient-3.x/methods/head.html
https://security.stackexchange.com/questions/62811/should-i-disable-http-head-requests
Apache 2.2.2 response on HEAD requests
As Lurii mentioned, the content length is affected by your request type.
With GET requests, a non-matching content length may result in a hanging client, so LiteSpeed will verify the content length before sending the header to the client.
Using a HEAD request should return the content length as expected.
I want to send a custom HTTP response back to an application requesting a GET to a php script. The body is will be in binary format (octet-streams). I'm wondering if there is a simple way to do this? I am looking into the HttpResponse class in PECL but is having trouble installing it right now. I do not really need all the other functionalities that goes with it so I'm looking for something simpler.
Any help would be appreciated.
PHP has a header() function built in, so you can customise your response without requiring extra libraries:
<?php
header('Content-Type: application/octet-stream');
header('X-Powered-By: l3utterfly');
echo $binary_data;
?>
You can always set HTTP Headers using header() function, and then simply output binary data using print, echo or any other usual way. Send Content-Type http header to octet stream and it should work all right.
You can use the header function to send back whatever response you want. If you want to send back custome response codes, you could use:
<?
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
//change the code and message to whatever. But I would keep it valid codes so browsers can handle it.
//see http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
header($protocol . ' 404 Not Found');
exit();
?>
And if you want to send binary data, change the header to the correct content-type and echo the binary data.
I know I can generate chunked response in PHP simply by introducing a sleep() in the output.
But is it possible to also generate a Trailer HTTP section in PHP? If not, is it possible in general in Apache 2.2?
I need it for testing purposes.
PHP will send a chunked response by default if headers are sent and no Content-Length header was specified. If you're familiar with the HTTP spec, this is the only logical thing to do since the client on the other end needs to know when the HTTP message you're sending ends so it can stop reading.
If you want to do this manually, you need to ...
Send the appropriate headers yourself and call flush()
Manually output the chunked HTTP message
So you might do something like the following. The idea is that you need to manually send your own headers and manually chunk your own message. If you simply don't send a Content-Length header, however, PHP will send a chunked message for you by default.
header("Transfer-encoding: chunked");
header("Trailer: X-My-Trailer-Header");
flush();
echo dechex(strlen($myChunk)) . "\r\n";
echo $myChunk;
echo "\r\n";
flush();
echo "0\r\n";
flush();
echo "X-My-Trailer-Header: some-value\r\n";
flush();
I was wondering if there are any problems or difference between sending normal headers before or after sending cookie headers. Do some browsers prefer a certain order to headers? If the cookie header is to large would subsequent headers never be parsed?
setcookie("TestCookie", $value);
header("Content-type: text/javascript");
or
header('Location: http://www.example.com/');
setcookie("TestCookie", $value);
or
setcookie("SuperLargeCookie", $massive_value);
setcookie("TinyCookie", $small_value);
header("Status: 404 Not Found");
There is no difference. The Http protocol does not specify that headers are to be in a certain order. Browsers do not differentiate based on the order of headers either.
The total length of Http headers does have a limit. This limit is imposed by the server and not the browser. Typically between 8K and 16K. However this is configurable.
It really doesn't matter as long as the other HTTP headers have not been sent. setcookie() actually writes a header itself:
Set-Cookie: SuperLargeCookie=whatever; Max-Age=3600; Version=1
similar to a header() call:
Location: http://www.example.com/redirect
HTTP messages span packets all the time, so you'd be hard-pressed to overfill one unless you're jamming tons of kilobytes in there. If you need to do that, consider a better design. Browsers don't care about the order of headers since different servers (and applications) append headers all the time. Cookies are implemented as HTTP headers, so they should appear like so in the HTTP request:
Cookie: TestCookie=value\r\n
Content-type: text/javascript\r\n
\r\n
I'm not sure what the Status header is supposed to do in your example, but I don't think it's right since the webserver will set a 200 OK response code if the code executes correctly... The header function page has this examaple:
<?php
header("HTTP/1.0 404 Not Found");
?>
With the PHP header function, just make sure you're not writing any text out before issuing it. Otherwise, you could mess everything up.
I didn't see any difference with or without this head information yet.
Define "necessary".
It is necessary if you want the browser to know what the type of the file is. PHP automatically sets the Content-Type header to text/html if you don't override it so your browser is treating it as an HTML file that doesn't contain any HTML. If your output contained any HTML you'd see very different outcomes. If you were to send:
<b><i>test</i></b>
Content-Type: text/html; charset=UTF-8 would display in the browser text in bold and italics:
✅ OK
whereas Content-Type: text/plain; charset=UTF-8 would display in the browser like this:
<b><i>✅ OK</i></b>
TLDR Version: If you really are only outputing plain text with no special characters like < or > then it doesn't really matter, but it IS wrong.
PHP uses Content-Type text/html as default, which is pretty similar to text/plain and this explains why you don't see any differences.
text/plain content-type is necessary if you want to output text as is (including < and > symbols).
Examples:
header("Content-Type: text/plain");
echo "<b>hello world</b>";
// Displays in the browser: <b>hello world</b>
header("Content-Type: text/html");
echo "<b>hello world</b>";
// Displays in the browser with bold font: hello world
It is very important that you tell the browser what type of data you are sending it. The difference should be obvious. Try viewing the output of the following PHP file in your browser;
<?php
header('Content-Type:text/html; charset=UTF-8');
?>
<p>Hello</p>
You will see:
hello
(note that you will get the same results if you miss off the header line in this case - text/html is php's default)
Change it to text/plain
<?php
header('Content-Type:text/plain; charset=UTF-8');
?>
<p>Hello</p>
You will see:
<p>Hello</p>
Why does this matter? If you have something like the following in a php script that, for example, is used by an ajax request:
<?php
header('Content-Type:text/html; charset=UTF-8');
print "Your name is " . $_GET['name']
Someone can put a link to a URL like http://example.com/test.php?name=%3Cscript%20src=%22http://example.com/eviljs%22%3E%3C/script%3E on their site, and if a user clicks it, they have exposed all their information on your site to whoever put up the link. If you serve the file as text/plain, you are safe.
Note that this is a silly example, it's more likely that the bad script tag would be added by the attacker to a field in the database or by using a form submission.
Setting the Content-Type header will affect how a web browser treats your content. When most mainstream web browsers encounter a Content-Type of text/plain, they'll render the raw text source in the browser window (as opposed to the source rendered at HTML). It's the difference between seeing
<b>foo</b>
or
foo
Additionally, when using the XMLHttpRequest object, your Content-Type header will affect how the browser serializes the returned results. Prior to the takeover of AJAX frameworks like jQuery and Prototype, a common problem with AJAX responses was a Content-Type set to text/html instead of text/xml. Similar problems would likely occur if the Content-Type was text/plain.
Say you want to answer a request with a 204: No Content HTTP status.
Firefox will complain with "no element found" in the console of the browser.
This is a bug in Firefox that has been reported, but never fixed, for several years.
By sending a "Content-type: text/plain" header, you can prevent this error in Firefox.
no its not like that,here is Example for the support of my answer ---->the clear difference is visible ,when you go for HTTP Compression,which allows you to compress the data while travelling from Server to Client and the Type of this data automatically becomes as "gzip" which Tells browser that bowser got a zipped data and it has to upzip it,this is a example where Type really matters at Bowser.