Relative Redirect

Small, short code snippets that other people may find useful. Do you have a good regex that you would like to share? Share it! Even better, the code can be commented on, and improved.

Moderator: General Moderators

User avatar
hawleyjr
BeerMod
Posts: 2170
Joined: Tue Jan 13, 2004 4:58 pm
Location: Jax FL & Spokane WA USA

Relative Redirect

Post by hawleyjr »

Thanks to Roja in the following post:

viewtopic.php?t=35572&highlight=

and using php.net

http://us2.php.net/header

Code: Select all

Note:  HTTP/1.1 requires an absolute URI as argument to Location:
including the scheme, hostname and absolute path, but some clients
 accept relative URIs. You can usually use $_SERVERї'HTTP_HOST'],
$_SERVERї'PHP_SELF']  and dirname() to make an absolute URI from a 
relative one yourself:

<?php
header(&quote;Location: http://&quote; . $_SERVERї'HTTP_HOST']
                     . dirname($_SERVERї'PHP_SELF'])
                     . &quote;/&quote; . $relative_url);
?>
I'm now using the following function for redirecting pages. Any comments appreciated.

Code: Select all

function relativeRedirect( $relative_url ){
	
	if($relative_url{0} != DIRECTORY_SEPARATOR){
		$relative_url = DIRECTORY_SEPARATOR.$relative_url;
	}
	
	if($_SERVER['HTTPS'] == 'on')
		$http = 'https://';
	else
		$http = 'http://';
	
	header("Location: "  $http . $_SERVER['HTTP_HOST']
                     . dirname($_SERVER['PHP_SELF'])
                     . $relative_url);
        exit;	
	
}
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

Here is a little extension:

Code: Select all

<?php
function redirect($location)
{
  $ports = array('https' => 443, 'http' => 80);
  $prefix = empty($_SERVER['HTTPS']) ? 'http' : 'https';
  $url = $prefix;
  $url .= $_SERVER['SERVER_PORT'] != $ports[$prefix] ? ':' . $_SERVER['SERVER_PORT'] : '';
  $url .= '://';
  $url .= $_SERVER['HTTP_HOST'];

  if ($location{0} != '/')
  {
    $url .= dirname($_SERVER['PHP_SELF']);
  }

  $url .= $location;

  header('Location: ' . $url);
}
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Re: Relative Redirect

Post by Roja »

hawleyjr wrote: header("Location: " $http . $_SERVER['HTTP_HOST']
Grin.

This one is another gotcha I found over time..

$_SERVER['HTTP_HOST'] isn't as reliable as $_SERVER['SERVER_NAME'].

I ran into it on OpenBSD and Windows platforms, although I can't be sure which caused me to switch. I just always use SERVER_NAME instead now.
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

As I posted in the original thread, you'll want to check if a session is active and if the cookie ISN'T set, if both are true you'll want to append the SID here as PHP won't append it for you inside header calls.
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

modified..

Code: Select all

<?php
function localredirect($location)
{
  $ports = array('https' => 443, 'http' => 80);
  $prefix = empty($_SERVER['HTTPS']) ? 'http' : 'https';
  $url = $prefix;
  $url .= $_SERVER['SERVER_PORT'] != $ports[$prefix] ? ':' . $_SERVER['SERVER_PORT'] : '';
  $url .= '://';
  $url .= $_SERVER['SERVER_NAME'];

  if ($location{0} != '/')
  {
    $url .= dirname($_SERVER['PHP_SELF']);
  }

  $url .= $location;
  
  if (!isset($_COOKIE[session_name()]) && isset($_SESSION))
  {
    $pos = strpos($url, '?');
    if ($pos === false)
    {
      $url .= '?';
    }
    $url .= session_name() . '=' . session_id();
  }

  header('Location: ' . $url);
  exit;
}?>
pilau
Forum Regular
Posts: 594
Joined: Sat Jul 09, 2005 10:22 am
Location: Israel

Post by pilau »

Timvw could you please explain how does that work?
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

Hmm, one more little nitpick. If you need to append the SID, but don't need a '?' then you do need a & (or the XHTML &amp ; reference)
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

@nielsene: Meaby i don't get it... But & is only used in html :)

@pilau: it works like this:

- it adds http or https
- then it looks at the portnumber and if it's not the default 80/443 it adds the portnumber
- then we add the servername
- if the location doesn't start with / we calculate the base path and add that
- then we add the location
- then we add an eventual session id
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

@nielsene: i do get it ;)

Code: Select all

<?php
function localredirect($location)
{
  $ports = array('https' => 443, 'http' => 80);
  $prefix = empty($_SERVER['HTTPS']) ? 'http' : 'https';
  $url = $prefix;
  $url .= $_SERVER['SERVER_PORT'] != $ports[$prefix] ? ':' . $_SERVER['SERVER_PORT'] : '';
  $url .= '://';
  $url .= $_SERVER['SERVER_NAME'];
 
  if ($location{0} != '/')
  {
    $url .= dirname($_SERVER['PHP_SELF']);
  }
 
  $url .= $location;
  
  if (!isset($_COOKIE[session_name()]) && isset($_SESSION))
  {
    $pos = strpos($url, '?');
    if ($pos === false)
    {
      $url .= '?';
    }
    else
    {
      $url .= '&';
    }
    $url .= session_name() . '=' . session_id();
  }
 
  header('Location: ' . $url);
  exit;
}
?>
Roja
Tutorials Group
Posts: 2692
Joined: Sun Jan 04, 2004 10:30 pm

Post by Roja »

timvw wrote:@nielsene: i do get it ;)
Apparently, you didn't get it all.

'&' is invalid in source for html compliance. You should use '&amp;' instead. :)

Code: Select all

$url .= '&';
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

But a header string doesn't appear in html..
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

timvw wrote:@nielsene: i do get it ;)
Just in case other's don't:

In XHTML the '&' is not allowed to appear in the source html, except as part of an entity reference. This means you can't have
"plain" '&'s in your query strings if you want the page to validate according the various XHTML DTD's. You can however you use the entity reference &amp ; (remove the space between amp and ';' in actual use) in your urls and they still work right while maintaining validability.
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

What i meant with "i get it":

- I saw that the code only handled urls without '?'.
- So i added the case where there is already a '?' by appending an &


In case you want to do more kinky stuff, one could also consider using urlencode.
User avatar
nielsene
DevNet Resident
Posts: 1834
Joined: Fri Aug 16, 2002 8:57 am
Location: Watertown, MA

Post by nielsene »

timvw wrote: In case you want to do more kinky stuff, one could also consider using urlencode.
Actually as that link says, urlencode doesnot handle the &->&amp ; conversion, you have to either use htmlspecialchars/htmlentities, or change the arg_seperator in php.ini, or deal with it manually. And in many cases you still have to deal with it manually if you're dynamically generating urls.
timvw
DevNet Master
Posts: 4897
Joined: Mon Jan 19, 2004 11:11 pm
Location: Leuven, Belgium

Post by timvw »

I think those are 2 different levels...

- First one should use urlencode to build a valid url..

- A lot later, when it's decided to display it in a website (html) one should use htmlentities..
Post Reply