homepage Welcome to WebmasterWorld Guest from 54.166.105.24
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / Apache Web Server
Forum Library, Charter, Moderators: Ocean10000 & incrediBILL & phranque

Apache Web Server Forum

    
RedirectMatch, is this the best way?
john28uk




msg:4565195
 10:49 am on Apr 16, 2013 (gmt 0)

Hi

I am condensing some of my site, I have a lot of directories that can be combined, is the 301 redirect below the best way of doing this?

Is there not a way of putting the redwidgets for example into one command to redirect to allredwidgets?

RedirectMatch 301 /tinyredwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]
RedirectMatch 301 /littleredwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]
RedirectMatch 301 /bigredwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]
RedirectMatch 301 /massiveredwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]


RedirectMatch 301 /tinygreenwidgets/(.*) http://www.example.com/allgreenwidgets/$1 [R=301,L]
RedirectMatch 301 /littlegreenwidgets/(.*) http://www.example.com/allgreenwidgets/$1 [R=301,L]
RedirectMatch 301 /bigrgreenwidgets/(.*) http://www.example.com/allgreenwidgets/$1 [R=301,L]
RedirectMatch 301 /massivegreenwidgets/(.*) http://www.example.com/allgreenwidgets/$1 [R=301,L]


RedirectMatch 301 /tinybluewidgets/(.*) http://www.example.com/allbluewidgets/$1 [R=301,L]
RedirectMatch 301 /littlebluewidgets/(.*) http://www.example.com/allbluewidgets/$1 [R=301,L]
RedirectMatch 301 /bigrbluewidgets/(.*) http://www.example.com/allbluewidgets/$1 [R=301,L]
RedirectMatch 301 /massivebluewidgets/(.*) http://www.example.com/allbluewidgets/$1 [R=301,L]



Thanks John

 

lucy24




msg:4565344
 6:15 pm on Apr 16, 2013 (gmt 0)

Is there not a way of putting the redwidgets for example into one command to redirect to allredwidgets?

Yes, there is. In fact your rules as written don't even require RedirectMatch; they're simple Redirect rules. That's assuming for the sake of discussion that you have NO RewriteRules anywhere, so mod_alias (Redirect by that name) remains OK to...

:: grind to a screeching halt as I look more closely ::

You've garbled the syntax of two different modules. RedirectMatch 301 is mod_alias (Redirect by that name). The [R=301,L] flags belong with mod_rewrite.

Either way, you certainly don't need all those separate little rule-lets.

RedirectMatch 301 /tinyredwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]
RedirectMatch 301 /littleredwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]
RedirectMatch 301 /bigredwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]
RedirectMatch 301 /massiveredwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]

(which is wrong in any case)

=

either
RedirectMatch 301 /(tiny|little|big|massive)redwidgets/ http://www.example.com/allredwidgets/
or
RewriteRule (tiny|little|big|massive)redwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]

A key difference between mod_alias and mod_rewrite is that mod_alias (Redirect by that name) reappends the rest of the path; you don't have to capture anything after the part you're changing. mod_alias (RewriteRule, which can create a full-fledged 301 redirect) throws everything away, so anything you need to reuse has to be captured.

You don't say whether this is happening in htaccess or your config file, but I'm guessing htaccess. The "pattern" part of a rule has a leading slash in the config file but not in htaccess. The "target" of any redirect-- whether by mod_alias or mod_rewrite-- begins with the full protocol and domain name, so don't change that part.

Do you currently use mod_rewrite for anything, anywhere in your htaccess? If so, you need to change any existing Redirect or RedirectMatch rules to use mod_rewrite instead. If there are lots of them, I've got a simple Regular Expression that you can plug into a text editor and change them all at once.

john28uk




msg:4565402
 9:19 pm on Apr 16, 2013 (gmt 0)

Hi thanks for the reply

As you can see I am not 100% sure what I am doing, my htaccess file is used to create my directories, I have tried both ways you showed but they dont redirect as required. I include my file below with example replacing my domain


RewriteEngine On
RewriteBase /

RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule (.*) http://www.example.com/$1 [R=301,L]

RewriteRule ^(.*)/(.*)/page-(.*).html$ /?seo_county&country=$1&county=$2&pag=$3 [S=3]
RewriteRule ^(.*)/page-(.*).html$ /?seo_country&country=$1&pag=$2 [S=3]
RewriteRule ^(.*)/(.*)/$ /?seo_county&country=$1&county=$2 [S=1]
RewriteRule ^(.*)/$ /?seo_country&country=$1
RewriteRule ^(.*)/(.*)/(.*)-(.*).php$ /?seo_product&country=$1&county=$2&name=$3&town=$4


This is one of a few problems I am having, forcing the directories to have a backslash I also cannot get working, I tried using this



RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.(html|php)$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://www.example.com/$1/ [L,R=301]


Any help most appreciated

Regards John

lucy24




msg:4565449
 1:20 am on Apr 17, 2013 (gmt 0)

:: wanders off sobbing brokenly ::

:: wanders back after finding that the question next door is worse ::

RewriteCond %{HTTP_HOST} !^www\.example\.com
RewriteRule (.*) http://www.example.com/$1 [R=301,L]

This needs to be your very last redirect. That means it will come immediately before all RewriteRules that issue a rewrite alone (the ones ending in [L] by itself). The wording isn't optimal, but there are thousands of other threads to deal with that. Start by putting it in the right place.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.(html|php)$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://www.example.com/$1/ [L,R=301]

What are you trying to do here? If you're talking about requests for real directories that physically exist, you don't need a rule at all. That's what mod_dir is for. The Directory-Slash Redirect is one of its two jobs; the other is auto-indexing, which nobody uses. Are you trying to put the poor thing out of work?

RewriteRule ^(.*)/(.*)/page-(.*).html$ /?seo_county&country=$1&county=$2&pag=$3 [S=3]
RewriteRule ^(.*)/page-(.*).html$ /?seo_country&country=$1&pag=$2 [S=3]
RewriteRule ^(.*)/(.*)/$ /?seo_county&country=$1&county=$2 [S=1]
RewriteRule ^(.*)/$ /?seo_country&country=$1
RewriteRule ^(.*)/(.*)/(.*)-(.*).php$ /?seo_product&country=$1&county=$2&name=$3&town=$4

:: deep breath ::
:: calm ::
:: focus ::
:: remember, he's not doing this on purpose ::

Now then. Take three steps back and explain in English what this group of rules is trying to do. "User clicks or types such-and-such. I want them to see material that really lives and thus-and-so." Like that.

Now back to the original problem you posted about.

What exact rule(s) did you try, and what happened when you tried? Since it's a redirect, start with what your browser's address bar says before and after.

You may want to fire up Live Headers to see what the browser is asking for. But unless there are extra redirects along the way, it may not be necessary. Either the rule gets triggered or it doesn't.

Remember that nothing in a RewriteRule has to exist, unless you're specifically checking for existence (the -f and -d conditions). So go ahead and make "dummy" rules that say things like

RewriteRule ^(red|blue|green)foobar.html http://www.example.com/allmyfoobars.html [R=301,L]

and practice asking for "http://www.example.com/redfoobar.html" until you see that the rule is working. Make sure you have a pretty 404 page, because you'll be seeing a lot of it :) Note that here I'm talking about literal text "foobar.html" or "widget.html" or "nonsense.html" or whatever unlikely name makes you happy. The idea is that you're testing your rule on requests that no passing human will make in real life, so it doesn't matter if the rule works or not.

g1smd




msg:4565574
 10:11 am on Apr 17, 2013 (gmt 0)

Rules with
(.*) at the beginning or the middle of a pattern can be optimised a LOT. Use ([^/]+)/ or ([^/-]+)- or ([^/.]+)\. as appropriate.

Mixing Redirect/RedirectMatch in the same file as RewriteRule is asking for trouble. Forget that Redirect and RedirectMatch ever existed and use RewriteRule for everything.

Escape literal periods in patterns. Remember "." matches ANY single character and "\." matches a literal period.

john28uk




msg:4565739
 7:12 pm on Apr 17, 2013 (gmt 0)

Hello, sorry to confuse

Let me explain if I can

The site is a php mysql database site, no physical directories are used, the site itself is divided into sections based on location, these are country then county, the listings are then shown, these can then be clicked to see the listing as required.

With this

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !\.(html|php)$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ http://www.example.com/$1/ [L,R=301]


I am trying to force a forward slash on each directory if it does not have one when the link is from other sources, the reason is that I get a 404, for example - country/county/ works ok but country/county gets the 404

Back to the original problem, I tried both rules, pasting into the address bar, no redirect happened, just kicked to the 404 page.

I hope this post is better than it neighbour :)

John

john28uk




msg:4566282
 10:26 am on Apr 19, 2013 (gmt 0)

Hi

Anybody got any suggestions for these problems?

Thanks John

System
redhat



msg:4566751
 11:33 am on Apr 19, 2013 (gmt 0)

as suggested by the OP i thought it was worth continuing this discussion of "regex efficiency with the ambiguous, greedy and promiscuous .*" in its own thread.

10 messages were cut out to new thread by phranque. New thread at: apache/4566749.htm [webmasterworld.com]
5:43 pm on Apr 20, 2013 (utc -7)

[edited by: phranque at 12:46 am (utc) on Apr 21, 2013]
[edit reason] context [/edit]

john28uk




msg:4566655
 7:01 pm on Apr 20, 2013 (gmt 0)

Hello, thank you very much Lucy, your explanation was great.

I will leave you other guys to debate the optimization :)

Regards John

lucy24




msg:4566456
 7:51 pm on Apr 19, 2013 (gmt 0)


mod's note: sorry for the slice and dice. this is the explanation provided by lucy24 to which john refers above.



System: The following message was cut out of thread at: http://www.webmasterworld.com/apache/4566749.htm [webmasterworld.com] by phranque - 5:49 pm on Apr 20, 2013 (utc -7)


The site is a php mysql database site, no physical directories are used

Ah, gotcha. So essentially you need to make a rule that does exactly what mod_dir does, only with nonexistent directories. Here it's a big help if none of your directory names contain literal periods. Can I assume you are not apache dot org, whose site is littered with /2.4/ and the like? If you have no literal periods to worry about, then capturing extensionless URLs is a snap because the body of your rule need only say
^([^.]+[^./])$
meaning "no periods anywhere, and the final character is also not allowed to be a directory slash". If you don't currently use extensionless URLs for pages, then a request in this form can only be for a directory. And if you DO use extensionless page URLs, it's a non-problem because you'll be dumping the whole thing on your php anyway ;)

RewriteRule (tiny|little|big|massive)redwidgets/(.*) http://www.example.com/allredwidgets/$1 [R=301,L]

This ought to work. If you don't use an opening anchor, then it doesn't even matter if you are in htaccess (no leading slash) or config (leading slash).

But wait! I've been assuming that these are top-level requests. If there is other stuff before my-new-improved-widgets-page.html, then you have to capture that too. Since you're working with pages that formerly existed, you should be able to give the literal text. The more tightly you constrain your rule, the faster mod_rewrite can be outta there. May not matter right now, but it will make a big difference when you start getting a million daily visitors and your server is creaking at the joints :)

So, for example-- assuming htaccess--

RewriteRule ^directory/fat(red|blue|green)widgets/(.*) http://www.example.com/directory/allfatwidgets/$1[R=301,L]


Note that if we're dealing with material that comes before the part you're changing, there's no significant difference between mod_rewrite and mod_alias. But since you talk about nonexistent directories I have to assume you've already got mod_rewrite doing some things. That means you need to ditch any rules that currently use mod_alias (Redirect or RedirectMatch by that name) and convert them to mod_rewrite.

Any rule that creates a redirect goes before the rules that create rewrites alone. If it isn't your own server, the only way you can be sure this happens is by doing everything in the same module.

[edited by: phranque at 12:57 am (utc) on Apr 21, 2013]
[edit reason] point of order [/edit]

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / Apache Web Server
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved