I have a custom 404 page which works fine except for the message I want to display on this page.
I would like it to say the url of the page which can't be found but instead it displays the url of the 404 page.
Here's what I have...
You were looking for <?php echo $_SERVER['REQUEST_URI'] ?>.
The htaccess file contains the line: ErrorDocument 404 /404/
You need to use $_SERVER['HTTP_REFERER'] instead - that will be the address they requested first.
This only works in the exact case described in the question - where the browser has actually been redirected to the 404 page. In that situation, $_SERVER['REQUEST_URI'] contains the URI of the 404 page rather than the originally requested page as described.
Using Apache's ErrorDocument 404 /handle404.php in the site config or .htaccess would mean that $_SERVER['REQUEST_URI'] would actually work, but a more robust solution is the option in the update below.
Update:
Apparently $_SERVER['REDIRECT_URL'] might be a better bet however, having searched around a bit.
For both cases, as mentioned by the commenters below, bear in mind that any headers are just as prone to malicious content as $_POST, $_GET and others, so process them before outputting anything.
Update 2:
Didn't see the post from #Janoz below - he correctly mentions REDIRECT_URL.
From the perspective of the php page, that really is the request uri. Showing the error page is done by the webserver. Apache for example will add some extra server variables. REDIRECT_URL is probably the one you are looking for.
I did not write this function but it is what I use to do the same thing:
function selfURL() {
$s = empty($_SERVER["HTTPS"]) ? ''
: ($_SERVER["HTTPS"] == "on") ? "s"
: "";
$protocol = strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
$port = ($_SERVER["SERVER_PORT"] == "80") ? ""
: (":".$_SERVER["SERVER_PORT"]);
return $protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI'];
}
function strleft($s1, $s2) {
return substr($s1, 0, strpos($s1, $s2));
}
then to print it:
<?php print(selfURL()); ?>
If a page doesn't exist you redirect him to the 404 page? Idealy, I would display the 404 directly on the page which wasn't found. This way, you don't have to redirect, and you can correctly use REQUEST_URI. And the code for your 404 can still be centralized!
use file_exists to check whether the file your user is looking for exists or not. if it doesn't the redirect them to a custom made error page.
Related
I am not even A PHP newbie. But I need to call BS on a outside consultant who has come to my company and told me something was impossible.
Is it possible in PHP to simply create a webpage that displays the URL requested by the user.
In other words: rather than echoing/Printing "Hello World"
I would like the page to print the URL that the user requested.
This can be accomplished with:
echo $_SERVER['REQUEST_URI']--
for a full list:
print_r($_SERVER)
Another useful one is $_SERVER['HTTP_HOST']
If you're going to do a redirect, you have more footwork to do, but a straightforward solution would be:
header("Location: {$site}?original_request={$_SERVER['REQUEST_URI']}"); - and then handle the rest in the page you redirect to.
I think what you are looking for is the full url. This can be done with.
$url = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
echo $url;
Just incase the port is included.
$port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
$url = "http://".$_SERVER['HTTP_HOST'].$port.$_SERVER['REQUEST_URI'];
Here ya go:
echo $_SERVER['PHP_SELF'];
In a sense, both you and the consultant are correct. In most cases, yes you can get the exact URL. In many cases, the URL will be approximate. In some cases, you might not get anywhere close to the requested URL.
Here are some barriers to building the exact URL:
The #fragment isn't sent
You don't know if :port was present (so you can't know whether to add it or not)
You don't know what outside PHP rerouting was done (eg in .htaccess)
You could get around these by having a hidden input variable that is filled by Javascript with the full URL, which is then posted. But then the argument is "well what if Javascript isn't turned on."
So, I'd say "yes you can" is the practical/pragmatic answer, while "no you can't" is the academic answer.
I am trying to use a php script that redirects visitors based on certain criteria. I use the script succesfully on an apache server however, I am experimenting with nginx and php-fpm and the same script doesn't seem to be working as it should.
header("Location: $url");
exit();
The strange thing is it appears to be appending the URL I am trying to redirect to to the original URL so the URL it tries to forward to looks like:
originaldomain.com/redirectdomain.com.
Has anybody ever come across this before where it as appending the redirect domain to the original URL instead of redirecting straight to it?
Please let me know if you need any further information to help.
You need to make sure the URL has http:// at the beginning of it, otherwise it thinks it's going to a path on your domain, and not a redirect to an actual site.
$url has to begin with http:// or https://
if (strpos($url, 'http') === 0 ) {
$newurl = $url;
} else {
$newurl = "http://" . $url;
}
Then just use $newurl in you header request :)
If the above answers are not yet fixed header redirect, you need to check in your php.ini file output_buffering on or off or set limit.
output_buffering = On
Right now, I am using a custom PHP solution to force WWW to be appended to my script URLs, since I am using WordPress' .htaccess rules to "clean up" index.php. The force WWW .htaccess rules are not compatible with WordPress' index.php cleanup rules.
With my script, you can browse to "http://scripturl.com/whatever" - my script then has a case for request URI "/whatever" and then does some action (or compiles the respective template) for that view.
I have added a series of checks prior to any any switches being called, which makes sure that the HTTP host from the REQUEST matches the HTTP host from a defined variable in my script. This enforces the addition of the "www".
My PROBLEM - is that (seemingly when only using IE) - when I enter a url, say "http://myscript.com/whatever", my script transforms the url to "http://www.myscript.com/whatever", as expected, and then redirects the header to the new URL. HOWEVER, if I change the URI request from "whatever" to "somethingelse", the page goes to "http://www.myscript.com/somethingelse" as expected, but for a brief second, "whatever" blinks in the url before the script redirects to "http://www.myscript.com/somethingelse".
To clarify: start with request "www.myscript.com/sam". request loads.
Change /sam to /bob -> page changes to "www.myscript.com/bob" but "/sam" flashes in the url bar briefly before /bob loads.
It just doesn't feel "clean". I feel like my code might be doing an extra header jump or something. I have contrasted this to wordpress, by going to "www.wordpressurl.com/valid-page", then changing the URI to "www.wordpressurl.com/another-valid-page" - I don't see "/valid-page" flash in the URL bar when attempting to access "/another-valid-page", and vice versa.
Here is my code:
// Requested URL built from url in address bar
$requested_url = is_ssl() ? 'https://' : 'http://';
$requested_url .= $_SERVER['HTTP_HOST'];
$requested_url .= $_SERVER['REQUEST_URI'];
// Correct url built from predefined variable
$correct_url = is_ssl() ? 'https://' : 'http://';
// "Correct" script url
$user_home = #parse_url('http://www.myscript.com');
if ( !empty($user_home['host']) )
$correct_url .= $user_home['host'];
else {
die('malformed url');
}
$correct_url .= $_SERVER['REQUEST_URI'];
// If URL in address bar is not proper, perform redirect (preserve URI)
if ($correct_url != $requested_url) {
hc_redirect($correct_url, 301);
}
// Get page from request, handle accordingly
$page = $_SERVER['REQUEST_URI'];
switch ($page) {
/* Index */
case '/':
echo "Index queried <br />";
break;
...
Why does the old URI flash in the navbar before the new URI is loaded (from the redirect)? Like I said, this only appears to happen in IE - but WordPress does not have this same behavior (in IE or any other browser), so I know there must be something wrong with my code, an "extra step" which is happening without my knowledge. I'm somewhat new to PHP.
Any thoughts?
Edit: hc_redirect, and other used funcs: http://pastebin.com/fVNEckEg
Your script continues to output data after you redirect, the browser waits for the data and only then redirects. If you don't need to continue execution of the script after you send the redirect header, stop the script's execution. For example:
// If URL in address bar is not proper, perform redirect (preserve URI)
if ($correct_url != $requested_url) {
hc_redirect($correct_url, 301);
die();
}
I have a website that was written assuming http:// is one and only protocol forever. Now i bought a SSL certificate but when i visit site calling it with https:// i get info in browsers that part of site is insecure. As i found i have some JS, CSS and images and files that i refer to using http:// in the HTML of the site.
So what is best practice to enable full https? Should i change my website in every place when i refer to image, CSS or JS, check if site was loaded with http or https and load the resource with according protocol? It seems like a lot of work for me and bit error prone. Is there any other way, easier to make the whole site fully secure?
Rather than linking to your css, js, and images with http://yoursite.com/css/file.css just use relative paths such as /images/image.jpg and /css/file.css this way it will work with both http and https, also if you change domains or copy your content to another domain, you shouldn't have to change all those links either.
Use relative paths. If you are pointing to something that is on the same site as yours, then you should not be using http://
If for some reason you still need to have http:// then just switch them all to https://. An http:// will never complain because it is pointing to https:// stuff, but an https:// page will complain if it is pointing to non-https stuff.
If you are pointing to content outside of your control, on another site for example, then you need to hope that you can get at that content via https instead. If you can't, then you're hosed and you either need to live with the error, get the content from somewhere else, or proxy the content through your own https connection.
To complement #drew010 's answer, you could use other domains and still refer to the current protocol with //, something like:
<img src="/pics/home.png" />
<img src="//my-cdn.com/pics/info.png" />
The latter example will point to https://.. from https://your-site.com and http://... from http://your-site.com.
the best practice would be either using relative path rather than absolute but sometimes absolute is a better option so you can do the following :
as I can imagine you have a file called config.php or common.php (a file that stores your common used vars and you include it in every page), so put this code there :
function selfURL() {
$s = empty($_SERVER["HTTPS"]) ? ''
: ($_SERVER["HTTPS"] == "on") ? "s" : "";
$protocol = strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
$port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
return $protocol."://".$_SERVER['SERVER_NAME'].$port.$_SERVER['REQUEST_URI'];
}
function strleft($s1, $s2) {
return substr($s1, 0, strpos($s1, $s2));
}
and then you can assign a var called $http to get the value of the function like :
$http = selfURL();
and then whenever you want to include anything like images, css, etc do something like :
<img src="<?=$http?>images/sample.png" />
this method is reliable as it works in any situation.
I posted this earlier
301 Redirect of Static HTML to Dynamic PHP Page
But have a new idea, and am wondering if there are any issues why I should NOT do this...
If someone tries to go to a dead page on our site like:
(domain)/somepage.html
That now exists here:
(domain)/dynamic.php?id=1
It fails and goes to a custom Error 404 page (/404.php)
If I look at the $_SERVER['REDIRECT_URL'] variable, I can see where they were trying to go. My idea is to add an include at the top of the 404.php page to check this value, and if it's in my list of items to redirect, then to use PHP to do the 301.
Something like this...
// -- php include at top of 404.php page
switch(trim($_SERVER['REDIRECT_URL'])){
case "/oldpage.html" : $location = "/dynamic.php?id=1"; break;
case "/oldpage2.html" : $location = "/dynamic.php?id=2"; break;
}
if(isset($location) && trim($location) != ''){
header ('HTTP/1.1 301 Moved Permanently');
header ('Location: '.$location);
exit(0);
}
// -- end of php include
This gives me a single point to enter in all the links I see in the google webmaster tools that are in blog entries, etc. that are now dead.
Thanks
Well, yes. 301, accompanied by a Location header, is the proper response for a request that you can positively identify as being moved.