3

me again. :) I will try to keep this more to the point.

Synopsis: I am trying to redirect URLs like this:

www.desktopscenes.com/Scenes from Yellowstone (2003)/slides/Morning Glory Pool.html

to this:

desktopscenes.com/Scenes_from_Yellowstone_-_2003/slides/Morning_Glory_Pool.htm

And I mostly have code that does this. And even inserts the "slides" part if it is left out. Here's the code.

RewriteEngine On
Rewritecond %{HTTP_HOST} ^(desktopscenes.com|www.desktopscenes.com)$ [nc]
RewriteRule ^(Scenes.*)\s(.*)$ $1_$2 [N,NE]
RewriteRule ^(Scenes.*)\((.*)$ $1-_$2 [NE]
RewriteRule ^(Scenes.*)\)(.*)/slides/(.*)html$ http://desktopscenes.com/$1$2/slides/$3htm [NE,R=301,L]
RewriteRule ^(Scenes.*)\)(.*)/slides/(.*)jpg$ http://desktopscenes.com/$1$2/slides/$3jpg [NE,R=301,L]
RewriteRule ^(Scenes.*)\)/([^/]*)jpg$ http://desktopscenes.com/$1/slides/$2$3jpg [NE,R=301,L]
RewriteRule ^(Scenes.*)\)/([^/]*)html$ http://desktopscenes.com/$1/slides/$2$3htm [NE,R=301,L]

It works fine IF I get a "well-formed" request passed. The problem is that when I pass a URL that doesn't match one of my "L" patterns, I get an endless loop. I thought that it would just fall off the end of the RewriteRules and return whatever the URL was at that point. Was I wrong about that?

For example, if I take the "(2003)" out of the request like so:

   http://www.desktopscenes.com/Scenes from Yellowstone/Morning Glory Pool.jpg

Then the rewrite trace log fills with zillions of entries showing that it is creating cascading junk like this:

/Scenes from Yellowstone/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg/Morning Glory_Pool.jpg ...

Each line has another entry.

So, clearly I am doing something very wrong here. Does anyone know what it is?

All I want is that if the URL matches my pattern it does the rewrite, and otherwise, it just leaves it alone. :)

Thanks in advance for your patience and help!

Something I tried

I put this after the other lines:

RewriteRule ^(.*)$ $1 [L]

Figuring it would just be "if you got here, then stop." Didn't work.

I am missing something fundamental here. Halp! :)

Info from Log

Here's a line from the rewrite log (IP omitted)

[15/Sep/2015:22:06:57 --0400] [www.desktopscenes.com/sid#80111ced0][rid#80a25a0a0/initial] (3) [perdir {my user folder}] applying pattern '^(Scenes.*)\\s(.*)$' to uri 'Scenes from Yellowstone/Morning Glory_Pool.html/Morning Glory_Pool.html/Morning Glory_Pool.html/Morning Glory_Pool.html/Morning Glory_Pool.html/Morning Glory_Pool.html/Morning Glory_Pool.html  

..... this "/Morning Glory_Pool.html" is appended hundreds of times.

This suggests it is getting stuck on the first RewriteRule. Even though it's not actually replacing all the spaces. Bear in mind this works fine if the URL is in the expected format. None of this makes sense to me, anyone else?

More Info from Another Experiment

I enabled the rules except the first one that replaces all the whitespace ("\s") with underscores. With this done the problematic URL no longer causes an infinite loop. Of course, the rest of the script now no longer does what's necessary, but that's a piece of info.

This seems like it should be the simplest part of this. I'm baffled.

And Another Try

Apparently you can limit the "N" tag with a number, so I set it to "N=20". Still locks up with an infinite loop.

More Oddness

Even if I remove the "N" from the initial rule, which means it should only replace ONE instance of a space with an underscore, the rule is called repeatedly and they all get replaced. Except sometimes I then get a server error. The rewrite_log shows "internal redirects". I am lost.

Yet Another Experiment

To try to simplify this down as much as possible, I stripped everything down to just this:

RewriteEngine On
Rewritecond %{HTTP_HOST} ^(desktopscenes.com|www.desktopscenes.com)$ [nc]
RewriteRule ^(Scenes.*)\s(.*)$ $1_$2 [L]

In theory, this should replace one instance of white space with an underscore and stop.

As a test, I put this in my browser:

http://www.desktopscenes.com/Scenes%20from%20Nowhere/Test%20This%20Else.jpg

And what I got was this error message:

 "The requested URL /Scenes_from_Nowhere/Test_This_Else.jpg was not found on this server."

Notice all the spaces have been turned to underscores!

This one line also generated 46 lines in a rewrite_log. I saved them to this file: http://www.desktopscenes.com/rewrite_log_one_request.txt

Notice how it says "INTERNAL REDIRECT" several times, and keeps running the same rule over and over again. It's even ignoring the "[L]" flag.

Slowly Learning Here

Okay I now understand that this is inherently interative, so it will keep calling the same code over and over regardless.

I guess what I don't understand is why in the error cases it is attaching another copy of the text after the last "/" character, which is causing the endless looping.

Man this is confusing.

Add Path Info Postfix?

This is being done over and over in the case where the errors occur. It is what is causing the infinite looping. But it only happens sometimes. How do I stop it?

Someone on another thread mentioned "Options -Multiview" but I am not sure what other effects that would have.

Thanks.

7
  • 2
    Welcome back me! You are asking good questions. We like that!! Hopefully @w3d can help you- he is the best!!
    – closetnoc
    Commented Sep 16, 2015 at 1:11
  • Is this a replacement question of your other question?
    – John Conde
    Commented Sep 16, 2015 at 1:17
  • Yes. I don't think my basic code is wrong, it works, it's just messing up requests it should be ignoring. (I closed the other one.) And thanks, closetnoc. Commented Sep 16, 2015 at 1:45
  • 1
    Ok, I officially closed the other question. It probably should be deleted since it serves no purpose but I'll leave it around for a day or two just in case you need to copy some info out of it. Next time just edit your question instead of creating a new one.
    – John Conde
    Commented Sep 16, 2015 at 1:49
  • 1
    So apparently this is all caused by an Apache bug, and adding "DPI" to the first line APPEARS to have fixed it. No wonder I have been going nuts. I'd still be grateful to anyone who can confirm this (or tell me I'm wrong!) Commented Sep 16, 2015 at 15:09

1 Answer 1

1

I would aproach this another way since .htaccess is gonna be messy. Part of creating code is keeping it maintainable. No-one is ever gonna touch that code again.

I'd use the help of another language like PHP (or another language you like) for this:

# Redirect if the url isn't what I'd like
RewriteCond %{REQUEST_URI} \s 
RewriteRule ^(.*) pretty_url.php?url=$1 [L]

The contents of pretty_url.php:

$url = preg_replace("/[\s]+/", "_", $_GET{'url']); // replace all spaces's
$url = strtolower($url);
header("Location: ".$url, true, 301); // permanent redirect
exit;

The permanent redirect tells the SEO bots that "This will be the URL used for this page from now on.".

1
  • Scripting this also helps keep your code portable. So if you end up on another webserver (e.g. NGINX) you won't have to go through this whole process again. Commented Oct 14, 2015 at 8:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.