Forum Moderators: phranque

Message Too Old, No Replies

rewrite fix 3 digits to 4

         

matc

11:29 am on Feb 24, 2004 (gmt 0)

10+ Year Member



hello,

I'm just tring to capture any 3 digit query based requests to change them to 4. e.g. =123 will be changed to =0123.

err... what am I doing wrong here?

RewriteCond %{QUERY_STRING} ^5\.shtml\?(this¦that)\=([0-9]{0,3})$
RewriteRule ^5\.shtml\?$1\=0$2[R,L]

cheers, ject

jdMorgan

3:08 pm on Feb 24, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



matc,

Welcome to WebmasterWorld [webmasterworld.com]!

For an internal rewrite:


RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{3})$
RewriteRule ^5\.shtml$ /5.shtml?%1=0%2 [L]

1. The filename and "?" are not part of the query string.
2. The RewriteRule must have a pattern consisting of the local pathname to be matched, and a substitution consisting of either a local path to be used instead of the original pathname, or a canonical URL to which the original request should be externally redirected.
3. RewriteRule back-references to variables in RewriteConds are made using "%1" and "%2", etc., rather that "$1", "$2", etc.
4. Character-escaping rules are a little different in mod_rewrite versus scripting languages, and you don't need to escape as many characters in mod_rewrite.
5. All of the code in this post assumes that the URL associated with the query string is http://www.example.com/5.shtml -- If that is not the case, then you will need to change the RewriteRules.

If you intend to do an external redirect, where the new URL is visible to visitors and search engines, then you should use a canonical URL for the substitution, and set the [R] flag to do a 301-Moved Permanently redirect:


RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{3})$
RewriteRule ^5\.shtml$ http://www.example.com/5.shtml?%1=0%2 [R=301,L]

Further, I note that your code is written to match and rewrite zero to three digits in your query string and do an external redirect. In this case, there is the possibility that three external redirects will occur, each one adding another pad digit. This would be highly inefficient, as it would require the client browser or robot to re-request the page three times.

If you do need to pad out zero-to-three digit numbers to four-digit numbers, then for an internal rewrite you could use:


RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{3})$
RewriteRule ^5\.shtml$ /5.shtml?%1=0%2 [L]
RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{2})$
RewriteRule ^5\.shtml$ /5.shtml?%1=00%2 [L]
RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9])$
RewriteRule ^5\.shtml$ /5.shtml?%1=000%2 [L]
RewriteCond %{QUERY_STRING} ^(this¦that)=$
RewriteRule ^5\.shtml$ /5.shtml?%1=0000 [L]

And if you do require an external redirect:

RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{3})$
RewriteRule ^5\.shtml$ http://www.example.com/5.shtml?%1=0%2 [R=301,L]
RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{2})$
RewriteRule ^5\.shtml$ http://www.example.com/5.shtml?%1=00%2 [R=301,L]
RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9])$
RewriteRule ^5\.shtml$ http://www.example.com/5.shtml?%1=000%2 [R=301,L]
RewriteCond %{QUERY_STRING} ^(this¦that)=$
RewriteRule ^5\.shtml$ http://www.example.com/5.shtml?%1=0000 [R=301,L]

Using the [N] flag, you could write a recursive ruleset to do the above in fewer lines, but it would be slower and would require you to place it at top of your .htaccess file -- at the very beginning of your RewriteRules; The brute-force position-independent code above is better, IMO.

Jim

matc

10:44 am on Feb 25, 2004 (gmt 0)

10+ Year Member



Thank you very much Jim. This is pretty interesting to say the least.

Previous to this post I wrote a few rewrite rules to handle some directory restructuring and naming convention changes on Apache. Unfortunately none to date developed to manipulate query strings as this was all done a while back by a mate.

The reason for my post is that I've been looking at clearing up on a few loop holes in the way the existing query string rewrites behave. There is a real need for a (this¦that) 4 digit query (that being the maximum limit) to be parsed and remain untouched as this is valid. However, if a user mis-types, or comes from a legacy link that only uses a 3 digit id in the QS the template falls apart, which is not exactly ideal.

I understand where you are coming from with what you have said as your explanation is nice and clear. There are a couple of other things I would like to ask you. , However, for the moment the only tricky bit I found is after running the various combinations the user might fall fowl of I have noticed something a little baffling.

There are a number of QS rewrites top level of my site and most of these don't look to conflict with what I'm doing, however, I'm not a expert in that dept.
Basically after inserting the new QS handlers and testing them the resulting Query gets written to 5 digits. For example, if I type in 08, 008, or 0008 this gets rewritten as 00008 (5)digit id.

Heres the code which you supplied :)
RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{3}[^&])$
RewriteRule ^5\.shtml$ [example.co.uk...] [R=301,L]
RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{2}[^&])$
RewriteRule ^5\.shtml$ [example.co.uk...] [R=301,L]
RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9][^&])$
RewriteRule ^5\.shtml$ [example.co.uk...] [R=301,L]
RewriteCond %{QUERY_STRING} ^(this¦that)=$
RewriteRule ^5\.shtml$ [example.co.uk...] [R=301,L]

Another strange thing I haven't seen before is that when I shortened the rewrite, knocking off one 0.

[example.co.uk...] [R=301,L]
RewriteCond %{QUERY_STRING} ^(this¦that)=$

I get the follwoing Alert msg in Mozilla:

"Redirection limit for this URL exceeded. Unable to load the requested page. This may be caused by cookies that are blocked."

I couldn't really see from the rewrite how the 5 digit would come into it. If you can offer any insights into how this can be curbed I can leave my hair is place :)

many thanks, ject

jdMorgan

3:52 pm on Feb 25, 2004 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



ject,

That is *not* the code I supplied, and the change is likely contributing to the problems. You are requiring "[^&]" -- "any character not an ampersand" at the end of your pattern, and therefore a digit will match there. So, one digit will be uncounted in this position, leading to your "count off-by-one" problem.

This change indicates a new requirement which was not discussed. I will hazard a guess that you may have additional (and optional) parameters following the (this or that) parameter. If that is the case, you'll need something like this:


RewriteCond %{QUERY_STRING} ^(this¦that)=([0-9]{3}[b](&.*)?[/b]$
RewriteRule ^5\.shtml$ http://www.example.co.uk/5.shtml?%1=0[b]%2%3[/b] [R=301,L]

from which you can derive the remaining rules.

Jim

matc

4:55 pm on Feb 25, 2004 (gmt 0)

10+ Year Member



Jim again thank you and *apologies* for clouding the issue by my own off-by-one style.

You are right the code you supplied has had my sticky fingers over it ^_^. I wanted to omit anyone from tagging an ampersand to the tail of the QS. It is not a big deal so I have now amended it properly for the purposes of closing the initial issue with 1/2/3 digit queries.

I was however really surprised by it being counted as a char and appended to the QS even though I was trying to omit the peach - It does make sense now when I look at it, but still fascinating!

I have appreciated you help with this so again thanks. I have learnt - not exactly catching my own fish totally yet but hopefully getting there.. err if you know what I mean!?.

thanks, ject