2

EDIT: As requested below, this is the entire ruleset for one product (obsolete now, as I should be able to consolidate these into ONE simple rule that looks for the productID#):

 RewriteRule  /mens-shirts-77/alice-in-wonderland-shirt-662.html$ http://www.domain.com/alice-in-wonderland-shirt-p160c3 [R=301]
 RewriteRule  /womens-shirts-92/womens-alice-in-wonderland-shirt-872.html$ http://www.domain.com/alice-in-wonderland-shirt-p160c3 [R=301]
 RewriteRule  /index.php?main_page=product_info*&products_id=(662|872)*$ http://www.domain.com/alice-in-wonderland-shirt-p160c3 [R=301]

And here's the original query string from above that I'm trying to wildcard down to just the productID:

/index.php?main_page=product_info&cPath=77&products_id=694&hipid=63ad73f32f5159a3d0f71b7b92404591

I would like to consolidate the three line rulesets above into a single line (the productID is always attached to any form of the URL, it's the ONLY thing I need to reference from any incoming URL)... this is my first shot, which I believe now is not going to be that easy, but you get the idea:

RewriteRule  *(662|872)*$ http://www.domain.com/alice-in-wonderland-shirt-p160c3 [R=301,L]

From what I understand now, I have to write out a regex that literally takes into consideration every single potential character in the URL's... but with that kind of overkill comes more potential for conflict... for example this rule works for the query string URL, but not the other two:

RewriteRule  ^/[A-Za-z.?_=&]+[0-9]+[A-Za-z.?_=&]+(662|872)[A-Za-z.?_=&]+[A-Za-z0-9._%+-]+  http://www.domain.com/alice-in-wonderland-shirt-p160c3 [R=301,L]

So is it even possible to build a single regex that will handle BOTH forms of URL's (query string AND rewritten) in one formula?

I'm familiar enough with regex to make something, but I'm not familiar enough to understand the right and wrong way to do things... this is for a long history SEO migration to a new platform... I have to get this expression right, and ideally consolidated down to it's most minimal form (there's 300 URL's with multiple incoming versions that need to be accounted for, as shown above)... I don't think I should have 1000 htaccess rules on an already graphic heavy ecommerce site. :/

Thanks for taking a look... I really need to get this right the first time!

5
  • Yes, it is better to consolidate your directives into as few as possible (using regex patterns), however, it doesn't look like what you have is "written properly" (* isn't simply a "wildcard"). Can you paste the complete rule and the URLs you want to redirect from (that is supposedly covered by this directive).
    – MrWhite
    Commented Jun 21, 2015 at 16:30
  • there are a few ways of handling large numbers of rewrites/redirects mentioned here httpd.apache.org/docs/2.2/rewrite/rewritemap.html you might want to benchmark against your own requirements for "ease of maintenance" and "efficiency". I personally found separate .conf files with a few .map files fine for 100s of rules. Server was not under heavy load however. Commented Jun 21, 2015 at 17:50
  • @john: I'm on a shared server, so no access to "rewritemaps"
    – JacksonJJ
    Commented Jun 22, 2015 at 18:42
  • @w3d: Updated the original question with more information... all I need to do is search the incoming URL for the product ID# (ALL other URL data can be ignored or wildcarded), then forward it to the associated new URL... given, each new URL has TWO old ProductID's that need to be consolidated, but it's not THAT complex of a scenario. Anyway, I obviously don't know what I'm doing, lol... just how detailed of a wildcard expression do I need to write to ignore everything except 3-digits? This is why I asked the question on here, I really don't understand the details of RegEx theory.
    – JacksonJJ
    Commented Jun 22, 2015 at 20:03
  • "I have to write out a regex that literally takes into consideration every single potential character in the URL's" - WOOO - HOLD IT RIGHT THERE! I think you've just invented a whole new level of complexity! - lol. Take a breath, read my answer and see what you think. Believe it or not, regex do make things simpler, not complex. :)
    – MrWhite
    Commented Jun 22, 2015 at 20:31

1 Answer 1

0

I see strange regex out there that appear to be more complex than necessary... for example, why use (.*) instead of just a *???

Because in regular expressions (as opposed to globbing patterns / standard wildcards) the * (asterisk) by itself does not mean anything. The * repeats the previous element 0 or more times. For example, the regex A* will match either nothing, "A", "AA" or "AAA", etc.

In your example *(662|872)*$, the first * is meaningless, it might even result in an error! The second * then repeats the previous element ("662" or "872") zero or more times. So, it will match "" (an empty string), "662", "872", "662662" or "662872", etc.

In fact, the regex you require is probably a lot simpler (not complex). For instance, (662|882) will match "662" or "882" anywhere in the string.

However, if you need to match both query strings and URL paths then this will add complexity as you can't do this with a single RewriteRule. You can't match the query string with the RewriteRule directive. You would need to do something like the following:

RewriteCond %{QUERY_STRING} products_id=(662|872) [OR]
RewriteCond %{REQUEST_URI} -(662|872)\.
RewriteRule ^ /alice-in-wonderland-shirt-p160c3 [R=301,L]

This assumes you are redirecting to the same domain, if not then you will obviously need the absolute URL in the RewriteRule substitution.

Is it even possible to build a single regex that will handle BOTH forms of URL's (query string AND rewritten) in one formula?

A single mod_rewrite directive - no.

However, do you really need to match the query string and the URL path? You state that one is "rewritten". Are users accessing the site with both URLs? If the URL has already been canonicalised then this could indeed be simplified, as you can simply ignore the query string version. Like so:

RewriteRule -(662|872)\. /alice-in-wonderland-shirt-p160c3 [R=301,L]

(The additional bits to the regex are just to ensure it doesn't match anywhere else in the URL. If you are sure "662" or "872" cannot appear anywhere else in the URL or part of another product id, then they can be removed.)

6
  • Thanks for the details man... yeah, I only need the expression to look for EITHER-OR when it comes to the ProductID#... I'm consolidating TWO different productID's into ONE new one... and yes, I believe the query string / URL path is entirely unnecessary (that's the reason I was trying to wildcard it out completely)... the expression is strictly about the ProductID#... any URL that comes in with the number (662) or (872), should forward to "alice-in-wonderland-shirt-p160c3"... that's it... anyway, I'll give it some testing... brb!!
    – JacksonJJ
    Commented Jun 22, 2015 at 20:40
  • Sorry, my comment above is misguided... I do need the querystring and URL path versions to be looked at (the old site won't be rewriting, but I still need to forward old bookmarks that used that rewrite)... I can't seem to get any querystring method to work tho, it keeps forwarding to the main page, not the "Alice" link (the URL path version works fine tho)... on a side note, can't we just ignore that it's a querystring URL and look for the 3-digit number the same as the URL path version? Three lines is just as bad as my original method, if not worse, since there's alternates to be processed.
    – JacksonJJ
    Commented Jun 22, 2015 at 21:24
  • Yes, it's not a great solution I'm afraid - there will be a lot of repetition - but there's not much you can do with .htaccess on a shared server. You can't "ignore that it's a querystring" - the RewriteRule pattern only matches against the URL-path, if you try to match against the query string it will never match. Your "original (three line) method" simply would not work for this reason. Whether 1000 directives will slow down your site is hard to tell - you'd have to try it!
    – MrWhite
    Commented Jun 22, 2015 at 21:54
  • However, there is an alternative... don't use .htaccess! You could do the redirection in your server-side language of choice. #1 Are you redirecting to a different domain? (I assume not.) #2 Would these "old" URLs normally trigger a 404? If so then this would probably be more efficient implemented as a "custom 404". Normal traffic to the new site (on the same server?) would not be affected.
    – MrWhite
    Commented Jun 22, 2015 at 21:58
  • I kinda figured the "ignore querystring" wouldn't work, just thought there may be a tweak forcing it to read as a txt path (since we only need the number)... the 404 idea is something I hadn't thought of, but I'm not certain that linkjuice will pass that way since it becomes a 2-step redirect... but honestly, most of the reason I'm holding onto the querystring aspect is for all the oddball social media stuff (like Pinterest) who manage to find the query URL... so I'll think I'll just redirect any querystring links to the main page... I think I'm good to go then, thanks for the help man!
    – JacksonJJ
    Commented Jun 22, 2015 at 23:16

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.