views:

183

answers:

5

I'm implementing a slug system for my website at the moment. I plan to redirect invalid slugs to the correct on that is stored in the database. E.g.

http://example.com/11/wrong-slug

Hit db, check if 11's slug is wrong-slug if not do 301 redirect

http://example.com/11/right-slug

Detect 301 and inform user that they followed an invalid link

Is it possible to identify the 301 redirect preferably using PHP so I can ask the user to update there bookmark etc.

Thanks, Jamie.

+1  A: 

Several solutions come to mind:

  1. You could try with get_headers() ah no, it dispatches a request to the URL, which is not what you want

  2. Since you are redirecting and testing for the redirect from the same machine anyway, you could simply write a message about the wrong slug into the user's session and display it the next time the view template is rendered. Many frameworks have a flash messenger component, that allow you do that easily, e.g. with Zend Framework you would use the following code in your controller action

    $flashMessenger = $this->_helper->getHelper('FlashMessenger'); $flashMessenger->addMessage('We did something in the last request');

  3. Instead of redirecting immediately when a wrong slug is found, you just render a View template that tells your user about the wrong slug and then use a meta or javascript redirect from the template. Optionally, you'd also write a plain link with the right slug to the template.

  4. And finally, you could also inject a custom header into the redirect via header(), which can then be read from your script. won't work either, because they will be lost once the browser got the redirect from the server

Gordon
So I could use get_headers(url) to return the status of the current page. However I don't see how I could use that to detect if they have allready been redirected. I figure I could add a flag to the redirected url. But again, that would lead to more problems.
Jamie
I was wrong, get_headers() is not what you are looking for, but check the updated answer for other possible solutions.
Gordon
+1  A: 

A solution might be to check the $_SERVER['HTTP_REFERER'] in the "new" page : if it is set and corresponds to the "old" page, it's probably because your user has been redirected -- which means you might want to display your message.

But note that the Referer is sent by the user's browser, and can be either disabled or forged -- so it's OK to use it to enhance the experience, but you must not rely on it for anything critical.

Pascal MARTIN
Just tried this method, a blank refferer is returned when visiting the redirected page.
Jamie
Ho, too bad -- I did a quick test here, and it seemed to be working :-(
Pascal MARTIN
I did:header("HTTP/1.1 301 Moved Permanently");header("Location: http://www.google.com");thenjavascript:alert(document.referrer);How did you do this?
Jamie
I used a RewriteRule in a .htaccess file -- but as you are using some PHP to do your redirection, you might as well use another solution than depending on the referer (for instance, use something based on a session variable)
Pascal MARTIN
+4  A: 

Alternatively you could append a GET parameter to your url (if you don't mind that), and check for it in your PHP script. Something like:

http://example.com/11/right-slug?corrected-from=http://example.com/11/wrong-slug

On the same note you can use the session or cookies, but you must take care to remove them after detection.

Zoran Regvart
You'll of course want to URL-encode that parameter, but this seems simpler than relying on what a particular browser might choose to send.
kdgregory
By adding the extra parameter the url again would change from http://example.com/11/right-slug so it would loop on itself.I could use a session if(invalid){session();redirect}) might be time I learnt about sessions!
Jamie
I'm not sure how you're choosing your redirects, but generally you would only look at the portion of the URI up to but not including the query string.
kdgregory
So your 301 destination location is rather */11/right-slug?corrected-from=…* than just */11/right-slug*? I don’t think that’s an option.
Gumbo
Becasue im using a slug system anything after /11/ is counted as a slug. Without enforcing a trailing slash and changing my mod_rewrite I cannot use any url parameters as users could end up bookmarking the corrected-from url.
Jamie
I think that in the long run you'll really regret including parameters (and more particularly, parameter order) in your slug.
kdgregory
A: 

Found a working solution:

  • Start session.
  • Check session, if $_SESSION['INVALID_SLUG'] exists display message then unset session

    else

  • Retreive slug from database e.g. /11/right-slug
  • Get current URI e.g. /11/wrong-slug
  • Compare, if different set $_SESSION['INVALID_SLUG'] and redirect to correct page

Any feedback? I realise this will not detect a 301 redirect itself more detect a trigger assosiated with the redirect.

Thanks for all the help.

Jamie
Keep in mind that sessions might not work (user has cookies turned off/blocked), the GET parameter solution is more reliable. If your page relies on sessions to work at all, this isn't a big deal.
mjy
It is impossible to detect a 301 redirect, because a redirect is nothing more than just telling the browser to do the same request to a different URL. The second request won't contain any information about any previous requests if you don't add it yourself (query parameter, session, cookie etc.).
Tomas Markauskas
That is what I suggested as solution #2 in my answer.
Gordon
A: 

I think the only useful option is to use a cookie.

When a URL with the wrong slug is requested, set a cookie for that URL without the slug:

$path = substr($_SERVER['REQUEST_URI'], 0, strrpos($_SERVER['REQUEST_URI'], '/')+1);
setcookie('wrong-slug', 1, 0, $path);

Then test if such a cookie exists and display your message:

if (isset($_COOKIE['wrong-slug'])) {
    echo 'The location of this resource has changed. Please update your bookmarks.';
}
Gumbo