homepage Welcome to WebmasterWorld Guest from 54.81.170.186
register, free tools, login, search, subscribe, help, library, announcements, recent posts, open posts,
Accredited PayPal World Seller

Home / Forums Index / Code, Content, and Presentation / Apache Web Server
Forum Library, Charter, Moderators: Ocean10000 & incrediBILL & phranque

Apache Web Server Forum

    
Rewrite Rule with folder-change, several parameters
Having trouble with a specific RewriteRule...
Fuchur84




msg:4524998
 3:59 pm on Dec 4, 2012 (gmt 0)

Hello :)!

I am quite new to this stuff, so please patient with me...

To get pretty urls (or at least better than before) I use the following RewriteRule:


RewriteRule ^contact-6-en(.*)$ /html/page.php?htaccess_4t5=1&page_id=6&lan=en$1
RewriteRule ^/html/page\.php\?page_id=6&lan=en(.*)$ contact-6-en$2 [R=301]


The first rule works as it should: If you insert http://example.com/contact-6-en you get to right page while in the addressbar there is still http://example.com/contact-6-en. (the &htaccess_4t5=1 is only there because I want to avoid circle-declarations. It is not necessary for the website to work).

The second rule however does not work... if I type in http://example.com/html/page_id=6&lan=en it just shows me the page but it will not "redirect" to "http://example.com/contact-6-en" or at least it does not change the adress in the addressbar.

This is what I try to accomplish:
1.) If you open the page by its pretty url, it should open internally the page but stay at the pretty url.
2.) If you open the page by its original link, it should redirect to the pretty url with 301-status.

Does someone know what I am doing wrong and can give me a little help here?
I am really not sure what I am doing wrong... but the second rule does not match in any case...

Thank you very much in advance for any help you can give!

See you
*Fuchur*

 

g1smd




msg:4525126
 11:41 pm on Dec 4, 2012 (gmt 0)

You need several more steps. Use previous threads (there are hundreds on this same question) for more detailed instructions.

You need to list the redirecting rule before the rewriting rule.

The target URL of the redirecting rule must include the protocol and canonical hostname.

Every rule needs the [L] flag.


RewriteRule cannot "see" query string data. You need a preceding RewriteCond immediately before the redirecting rule to look at that. The RegEx pattern in the Rule can match only the folder and file parts of the URL request.

The RegEx pattern in the Rule cannot match a leading slash. The requested URL is "localised" on a "per folder" basis. What this means is that when example.com/this-page is requested, the data passed to a RewriteRule in the root htaccess is "this-page" and NOT "/this-page".

The redirecting rule must also test THE_REQUEST with a preceding RewriteCond to be sure that a pointer with query strings in is as a result of a direct external incoming URL request and not as a result of a prior internal rewriting action. Failure to do this will cause an infinite redirect-rewrite loop. The data in THE_REQUEST is the literal request sent by the browser, e.g.
GET /this-page?param=foo HTTP/1.1
or similar.



After your redirecting rule and before the rewriting rule you need to add the standard non-www/www canonicalisation redirecting ruleset.

Add a blank line after every RewriteRule for human readability.

Comment your code explaining what each ruleset is supposed to do.

Use example.com in code examples in this forum. Using example.com suppresses the auto-linking function.

Fuchur84




msg:4525292
 12:37 pm on Dec 5, 2012 (gmt 0)

Thank you very much for the tipps...
I worked it out quite well with these now, but I still have one problem I could not solve...

This is how it looks now (:

RewriteEngine On

#PRETTY_URL_START#
##############################################################

# user enters contact-6-en into addressbar
RewriteRule ^contact-6-en(.*)$ /html/page.php?page_id=6&lan=en$1 [L]

# user enters /html/page.php?page_id=6&lan=en into addressbar
RewriteCond %{THE_REQUEST} ^(.*)page.php(.*)$ [NC]
RewriteCond %{QUERY_STRING} ^page_id=6(.*)&lan=en$ [NC]
RewriteRule ^(.*)$ http://www.example.com/contact-6-en? [R=301,L]

##############################################################

#PRETTY_URL_END#


Now I am at the next problem:
- I need to be able to change the languages of the website by giving a GET-parameter "&lan=de" for instance.
- The de-page however has another name which is something like "kontakt-6-de".
> Whenever a person types in or clicks on a link which is like "http://www.example.com/contact-6-en&lan=de"
it needs to be redirected permanently to "http://www.example.com/kontakt-6-de"

I know all the available languages, I know all the names I need for these pages.
(I generated these htaccess-files with a PHP-file, which gets these infos from a DB)

I tried it like this BELOW the rules above:

# user enters contact-6-en&lan=de into addressbar
RewriteCond %{REQUEST_URI} ^(.*)contact-6-en(.*)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)lan=de(.*)$ [NC]
RewriteRule ^(.*)$ http://www.patchwork3d.de/kontakt-6-de? [R=301,L]


But this does not work... I think it has to do with the rewritten URL or something like that... maybe he does not see this rule at all, since the one before is given the [L] modifier (L=last rule, right?) or it cannot see the URL contact-6-en at this state at all...

I am not sure... any tipps what I am doing wrong or how I could solve that?

Thanks again for any help and the help already given! :)
*Fuchur*

g1smd




msg:4525293
 12:44 pm on Dec 5, 2012 (gmt 0)

Before we get to that, the RewriteCond looking at THE_REQUEST should be looking for the presence of query strings.

The redirecting rule and its condition(s) should be listed before the rewriting rule.

You don't need a separate Condition looking for "page.php" simply put that pattern in the Rule.

Never use .* at the beginning or in the middle of the pattern. The .* means "read all the way to the end of the input". The .* can be used only at the end of a pattern, not at the start or in the middle. Additionally, uncaptured, or unused .* at the end of a pattern is redundant and can be omitted.

Every rule needs the [L] flag. The [L] flag means make this the Last rule if this rule matched.

Fuchur84




msg:4525335
 2:47 pm on Dec 5, 2012 (gmt 0)


Never use .* at the beginning or in the middle of the pattern. The .* means "read all the way to the end of the input". The .* can be used only at the end of a pattern, not at the start or in the middle. Additionally, uncaptured, or unused .* at the end of a pattern is redundant and can be omitted.


Hm... at the beginning it is very likely redundant, but in the middle or the end?

What if the link which is opened is "http://www.example.com/html/page.php?page_id=6&apple=15&lan=de"?

Or "http://www.example.com/html/page.php?apple=15&page_id=6&lan=de"?

(I can savely say it is never the case that page_id stands behind lan).

This would not be covered by something like:

RewriteCond %{QUERY_STRING} ^page_id=6&lan=de$ [NC]


So I would need something like:

RewriteCond %{QUERY_STRING} ^page_id=6(.*)&lan=de$ [NC]


Or am I wrong?
But I could make it non-greedy so it should only search for the first time this is happening:

RewriteCond %{QUERY_STRING} ^page_id=6(.*?)&lan=de$ [NC]

This is my next try... but it is still not working...


##############################################################

# user enters kontakt-6-de&lan=de into addressbar
RewriteCond %{REQUEST_URI} ^(.*)kontakt-6-de(.*)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)lan=de(.*)$ [NC]
RewriteRule ^kontakt-6-de(.*)&lan=de(.*)$ http://www.example.com/kontakt-6-de?$1$2 [R=301,L]

# user enters kontakt-6-de&lan=en into addressbar
RewriteCond %{REQUEST_URI} ^(.*)kontakt-6-de(.*)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)lan=en(.*)$ [NC]
RewriteRule ^kontakt-6-de(.*)&lan=en(.*)$ http://www.example.com/contact-6-en?$1$2 [R=301,L]

# user enters /html/page.php?page_id=6&lan=de into addressbar
RewriteCond %{QUERY_STRING} ^(.+)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)page_id=6(.*?)&lan=de(.*)$ [NC]
RewriteRule ^page\.php(.*)$ http://www.example.com/kontakt-6-de?$1$2$3 [R=301,L]

# user enters kontakt-6-de into addressbar
RewriteRule ^kontakt-6-de(.*)$ /html/page.php?page_id=6&lan=de$1 [L]


##############################################################

# user enters contact-6-en&lan=de into addressbar
RewriteCond %{REQUEST_URI} ^(.*)contact-6-en(.*)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)lan=de(.*)$ [NC]
RewriteRule ^contact-6-en(.*)&lan=de(.*)$ http://www.example.com/kontakt-6-de?$1$2 [R=301,L]

# user enters contact-6-en&lan=en into addressbar
RewriteCond %{REQUEST_URI} ^(.*)contact-6-en(.*)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)lan=en(.*)$ [NC]
RewriteRule ^contact-6-en(.*)&lan=en(.*)$ http://www.example.com/contact-6-en?$1$2 [R=301,L]

# user enters /html/page.php?page_id=6&lan=en into addressbar
RewriteCond %{QUERY_STRING} ^(.+)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)page_id=6(.*?)&lan=en(.*)$ [NC]
RewriteRule ^page\.php(.*)$ http://www.example.com/contact-6-en?$1$2$3 [R=301,L]

# user enters contact-6-en into addressbar
RewriteRule ^contact-6-en(.*)$ /html/page.php?page_id=6&lan=en$1 [L]

##############################################################

# user enters contact-6-en&lan=de into addressbar
RewriteCond %{REQUEST_URI} ^(.*)contact-6-en(.*)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)lan=de(.*)$ [NC]
RewriteRule ^contact-6-en(.*)&lan=de(.*)$ http://www.example.com/kontakt-6-de?$1$2 [R=301,L]

# user enters contact-6-en&lan=en into addressbar
RewriteCond %{REQUEST_URI} ^(.*)contact-6-en(.*)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)lan=en(.*)$ [NC]
RewriteRule ^contact-6-en(.*)&lan=en(.*)$ http://www.example.com/contact-6-en?$1$2 [R=301,L]

# user enters /html/page.php?page_id=6&lan=en into addressbar
RewriteCond %{QUERY_STRING} ^(.+)$ [NC]
RewriteCond %{QUERY_STRING} ^(.*)page_id=6(.*)&lan=en(.*)$ [NC]
RewriteRule ^page\.php(.*)$ http://www.example.com/contact-6-en?$1$2$3 [R=301,L]

# user enters contact-6-en into addressbar
RewriteRule ^contact-6-en(.*)$ /html/page.php?page_id=6&lan=en$1 [L]

##############################################################



I tried what you said, but I am quite sure it is not perfect... but it works okay for what it does... only the (pretty-url&lan=otherlan)-stuff is not working as it should...

See you and thanks in advance
*Fuchur*

g1smd




msg:4525366
 4:07 pm on Dec 5, 2012 (gmt 0)

When you use (.*) at the beginning the whole URL is placed into $1 by the RegEx parser. It then looks for e.g. "contact" after the end, and realises that ".*" is over-specified and the RegEx parser has to "back up retry" "trial match" the input hundreds, maybe thousands, of times to match the input string.
NEVER use (.*) at the beginning or in the middle of any RegEx patten. Use it only at the end where it means "and capture the rest of the input".

The RegEx pattern parser for the RewriteRule can only "see" the folder and filename part of any URL request. Only specify folder and filename details in the RegEx pattern of the RewriteRule. Do not specify quesry string stuff.

In the rules that redirect, you MUST test THE_REQUEST (not REQUEST_URI and not QUERY_STRING) for query strings, as this is the ONLY way to prevent an infinite redriect-rewrite loop. You need to be sure that if the pointer holds a query string it is from a literal external URL request that contained a query string and NOT as a result of a prior internal rewrite.

Rather than try to work on a huge chunk of code, continue with one redirect-rewrite pair. Once a pair is working, proceed with similar code for the other URL variations.

Fuchur84




msg:4525427
 6:48 pm on Dec 5, 2012 (gmt 0)

Okay, I got rid of the ^ and the $ at the beginning and the end of a regular expression pattern and now I am able to match much better... I got rid of the (.*) at beginning and in the middle and only use it at the end now.

But still the pretty-url with another lan-parameter is not working as it should.

My current code is:


RewriteEngine On

#PRETTY_URL_START#

# user enters kontakt-6-de&lan=de into addressbar
RewriteCond %{THE_REQUEST} kontakt-6-de(.*) [NC]
RewriteCond %{QUERY_STRING} lan=de(.*) [NC]
RewriteRule kontakt-6-de&lan=de(.*) http://www.example.com/kontakt-6-de?$1 [R=301,L]

# user enters kontakt-6-de&lan=en into addressbar
RewriteCond %{THE_REQUEST} kontakt-6-de(.*) [NC]
RewriteCond %{QUERY_STRING} lan=en(.*) [NC]
RewriteRule kontakt-6-de&lan=en(.*) http://www.example.com/contact-6-en?$1 [R=301,L]

# user enters /html/page.php?page_id=6&lan=de into addressbar
RewriteCond %{THE_REQUEST} html/page\.php\?page_id=6&lan=de(.*) [NC]
RewriteRule html/page\.php(.*) http://www.example.com/kontakt-6-de?$1 [R=301,L]

# user enters kontakt-6-de into addressbar
RewriteRule kontakt-6-de(.*) /html/page.php?page_id=6&lan=de$1 [L]

#PRETTY_URL_END#


What would be the next step to solve that?
1.) Person inserts "http://www.example.com/kontakt-6-de&lan=en" into addressbar.
2.) Server redirects permanently to "http://www.example.com/contact-6-en".

Thanks again
*Fuchur*

Fuchur84




msg:4525428
 6:59 pm on Dec 5, 2012 (gmt 0)

Ha, got it! It is working now as it should :):

Code:

##############################################################

# user enters kontakt-6-de&lan=de into addressbar
RewriteCond %{THE_REQUEST} kontakt-6-de&lan=de(.*) [NC]
RewriteRule kontakt-6-de&lan=de(.*) http://www.patchwork3d.de/kontakt-6-de?$1 [R=301,L]

# user enters kontakt-6-de&lan=en into addressbar
RewriteCond %{THE_REQUEST} kontakt-6-de&lan=en(.*) [NC]
RewriteRule kontakt-6-de&lan=en(.*) http://www.patchwork3d.de/contact-6-en?$1 [R=301,L]

# user enters /html/page.php?page_id=6&lan=de into addressbar
RewriteCond %{THE_REQUEST} html/page\.php\?page_id=6&lan=de(.*) [NC]
RewriteRule html/page\.php(.*) http://www.patchwork3d.de/kontakt-6-de?$1 [R=301,L]

# user enters kontakt-6-de into addressbar
RewriteRule kontakt-6-de(.*) /html/page.php?page_id=6&lan=de$1 [L]

##############################################################



Thank you very much again for all your help :). It really brought me were I needed to be and I think I understand much better how it works now!

See you and thanks again
*Fuchur*

g1smd




msg:4525440
 7:41 pm on Dec 5, 2012 (gmt 0)

I can't see the first two rules ever working as shown above.


You also need to soft anchor the patterns for query strings:

(^|&) before the first parameter.

(&|$) after the last parameter.
lucy24




msg:4525496
 11:10 pm on Dec 5, 2012 (gmt 0)

It is working now as it should

I think you have a rule working by accident. Test it with requests that are not supposed to work, and also with garbage requests that should never work.

What is the potential content of the capture in
# user enters kontakt-6-de into addressbar
RewriteRule kontakt-6-de(.*) /html/page.php?page_id=6&lan=de$1 [L]

? It cannot be a query string, because a RewriteRule does not "see" the query. Only a RewriteCond can do that. You may need the QSA flag-- but then you must make sure you are not duplicating a query that is already present. Otherwise you get an infinite loop.

Fuchur84




msg:4525553
 6:52 am on Dec 6, 2012 (gmt 0)

@g1smd:
I tested it with quite many different things and it works exactly as it should...

As soon as I put ^ and $ around my patterns, they are never matched again and nothing is working. The only way to make it happen with that is if I put in (.*) at the beginning and the end of the pattern (which should not be done). I don't understand it but it is that way...

I'll test it on another server soon, but for now it is doing what I want it to do on my V-Server.

Since not all of my links on the website are "pretty-urls" I tested it out already with many other combinations (simply by clicking around and I tried it with stuff that does not make sense too) and it only works for those I want it to work and the others are not matched. (which is correct)

The first two rules are working as they should too...
If the user inserts "example.com/kontakt-6-de&lan=en" s/he is redirected to "example.com/contact-6-en", which is correct.

@lucy24:
# user enters kontakt-6-de into addressbar
RewriteRule kontakt-6-de(.*) /html/page.php?page_id=6&lan=de$1 [L]


You are right here... I could get rid of (.*) at the end and will try it. There is nothing that can be matched there.

See you
*Fuchur*

g1smd




msg:4525585
 6:26 pm on Dec 6, 2012 (gmt 0)

I wrote a long reply here, but the server glitch has thrown it away. Sorry.

I had hoped to pull the posts from cache and paste them back in, but it's not to be.

lucy24




msg:4525711
 10:58 pm on Dec 6, 2012 (gmt 0)

Ah ha. Could swear there used to be something more in this thread. In fact my browser history says

http://www.webmasterworld.com/apache/4524996.htm#msg4525568

but pigheadedly refuses to let me get at a cached version, even though it's got to exist.

g1smd




msg:4525727
 11:38 pm on Dec 6, 2012 (gmt 0)

WebmasterWorld went off the air at about 12:30 UTC today.

Everything posted from 07:15 UTC until then escaped forever.

For me that was at least several thousand of my words.

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.
Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About
© Webmaster World 1996-2014 all rights reserved