Forward slashes in part numbers are breaking mod_rewrite rule - .htaccess

I've a simple mod_rewrite rule
RewriteRule ^product/([^/.]+)/([^/.]+)/?$ product.php?partNumber=$1&partName=$2 [L]
It works great for 99.99% of products but there are 3 or 4 products which have a forward slash in their part number (eg PART001/1)
which rewrites to something like:
/product/PART001/1/part-name-here-for-nice-seo
Obviously this doesn't work as it's looking in an extra directory. I need the part number passed correctly as it's used to look up the index in the database and fetch all the product's information.
Is there any way round this?

Looks like you just need to change the ([^/.]+) grouping in your regex to also match slashes. Try:
RewriteRule ^product/(.+)/([^/.]+)/?$ product.php?partNumber=$1&partName=$2 [L]

Related

URL rewrite with PHP and .htaccess

Can anybody advise how I can rewrite the following URL:
www.mydomain.com/products.php?product=product-name
At the moment, it works fine (I use $_GET to grab the unique product name and use it on my page) but I would like to be able to use the following URL format to get the same outcome:
www.mydomain.com/products/product-name
I've seen a few similar examples on here but cannot get them to work with my situation.
This is how your .htaccess will look like,
RewriteEngine On
RewriteRule ^products/([A-Za-z0-9-]+) /products.php?product=$1 [NC,L]
RewriteEngine On this is used to turn on the rewrite engine.
^products/([A-Za-z0-9-]+) matches the URL like (www.mydomain.com/products.php?product=product-name) where product name can be one or more of any combination of letters, numbers and hyphens.
And use that combination of letters in /products.php?product=$1 where $1 denotes the Product name.

.htaccess and dynamically generated SEO friendly URLs

I'm trying to build a website that may be called from the URL bar with any one of the following examples:
domainname.com/en
domainname.com/zh-cn/
domainname.com/fr/page1
domainname.com/ru/dir1/page2
domainname.com/jp/dir1/page2/
domainname.com/es-mx/dir1/dir2/page3.html
These page requests need to hit my .htaccess template and ultimately be converted into this php call:
/index.php?lng=???&tpl=???
I've been trying to make RewriteCond and RewriteRule code that will safely deal with the dynamic nature of the URLs I'm trying to take in but totally defeated. I've read close to 50 different websites and been working on this for almost a week now but I have no idea what I'm doing. I don't even know if I should be using a RewriteCond. Here is my last attempt at making a RewriteRule myself:
RewriteRule ^(([a-z]{2})(-[a-z]{2})?)([a-z0-9-\./]*) /index.php?lng=$1&tpl=$4 [QSA,L,NC]
Thanks for any help,
Vince
What's causing your loop is that your regex pattern matching /index.php. Why? Let's take a look:
First, the prefix is stripped because these are rules in an htaccess file, so the URI after the first rewrite is: index.php (query string is separate)
The beginning of your regex: ^(([a-z]{2})(-[a-z]{2})?), matches in in the URI
The next bit of your regex: ([a-z0-9-\./]*) matches dex.php. Thus the rule matches and gets applied again, and will continue to get applied until you've reached the internal recursion limit.
Your URL structure:
domainname.com/en
domainname.com/zh-cn/
domainname.com/fr/page1
domainname.com/ru/dir1/page2
domainname.com/jp/dir1/page2/
domainname.com/es-mx/dir1/dir2/page3.html
Either has a / after the country code or nothing at all, so you need to account for that:
# here -------------------v
^(([a-z]{2})(-[a-z]{2})?)(/([a-z0-9-\./]*))?$
# and an ending match here ------------^
You shouldn't need to change anything else:
RewriteRule ^(([a-z]{2})(-[a-z]{2})?)(/([a-z0-9-\./]*))?$ /index.php?lng=$1&tpl=$4 [QSA,L,NC]

Mod rewrite with query strings after .html

Im trying to perform a mod rewriting to my web site. And I used to do this rewriting for quite some time. Of course I am very much upto the task until I met new requirement to create a rewritten URL with query strings after .html
Example - http://kypseli/admin/catagory.html?parent_id=1
I have used this this regex.
RewriteRule ^([A-Za-z0-9-/_]+).([html])/?$ index.php?rt=$1&%{QUERY_STRING}
But the query string value (parent_id) not passing.
This is working with out the .html part for perfection.
http://kypseli/admin/catagory/?parent_id=1
But I want it with .html part, as I have found lots and lots of same technique usage every where in WWW. here is one example
http://www.espncricinfo.com/ci/content/video_audio/559158.html?genre=46
Can someone please help.
If you want to get all query string elements from the first query to be appended on your rewritten query you need to add the [QSA] flag to the rewriteRule, or [qsappend] if you prefer long and descriptive tags.
RewriteRule ^([A-Za-z0-9-/_]+)/?$ index.php?rt=$1 [qsappend]
Now I do not understand fully what you mean about '.html', but I hope this will be enough.
EDIT
your problem is maybe the dot, it should be escaped \. and it should be in the optionnal part if it is optionall so :
RewriteRule ^([A-Za-z0-9-/_]+)/?$ index.php?rt=$1 [qsappend]
RewriteRule ^([A-Za-z0-9-/_]+)\.html?$ index.php?rt=$1 [qsappend]
Or if you want only one rule, this should work (untested)
RewriteRule ^([A-Za-z0-9-/_]+)([\.html|/])?$ index.php?rt=$1 [qsappend]
And it's unsure you really need the ? in your rewriteRule, you may want to apply it even without query strings.

remove part of url via mod_rewrite

Is there any way to hide part of a Url via mod_rewrite. I am currently using part of the url, .htm, to split the page that is being requested and the query string.
Example
http://www.example.com/page/article/single.htm/articleid=8
This would let me know that the page requested is:
http://www.example.com/page/article/single
And the quest string is:
article=8
Ideally i would like the have this to work the same url without the .htm visible
http://www.example.com/page/article/single/articleid=8
The number of variables in the query sting varies as does the number of levels before the .htm so the rule would need to be dynamic
Thanks
To also do multiple querystring parameters, how do you want it to look? I started with this, which keeps this simple, then got trickier below.
http://www.example.com/page/article/single/articleid=8&anothervar=abc
Try this rule:
RewriteRule ^([^=]+)/(.+)$ $1.htm?$2 [NC,L]
This handles one or more querystring parameters, but does require at least one. This looks for anything without an = up to a slash, then everything else. Basically, it uses the = as the indicator of the path vs. the querystring portions; but actually splits it on the slash. (The NC is a habit of mine; not needed in this case, but when I leave it out I forget it when it's needed.)
To let querystrings be optional, so it could handle just
http://www.example.com/page/article/single
I found it easiest with two rules, instead of trying to mingle this into one rule:
RewriteRule ^([^=]+)$ $1.htm [NC,L]
RewriteRule ^([^=]+)/(.+)$ $1.htm?$2 [NC,L]
You can do something even prettier, using slashes for everything including multiple querystring parameters, like this:
http://www.example.com/page/article/single/articleid=8/anothervar=abc
It's a little hairy, but I think this works (couldn't let it go...)
Another rule handles replacing the slashes with ampersands, then doing the rewrite as above. This was easier to keep straight - maybe there's a way to do it all at once, but this was tricky enough for me:
RewriteRule ^([^=]+)$ $1.htm [NC,L]
RewriteRule ^([^=]+)/([^=]+=[^/]+)/([^=]+=.+)$ $1/$2&$3 [NC,LP]
RewriteRule ^/([^=]+)/(.+)$ /$1.htm?$2 [NC,L]
The first rule is as above, handling no querystrings at all. That just gets it out of the way.
The second rule is a loop LP, which is what I tend to find in examples whenever you have an unknown number of replacements. In this case, it's replacing the last querystring-slash with an ampersand, and looping until there's only one left (leaving that for the question mark in the third rule).
It's looking for the last one of these articleid=8/anothervar=abc where there are two parameters left. It replaces the slash with an ampersand like articleid=8&anothervar=abc
In words, it's looking for (and capturing in parentheses):
(not-equalsign) slash (not-equalsign equalsign not-slash) slash (not-equalsign equalsign anything)
This lines up as:
(not-equalsign) /page/article/single
slash /
(not-equalsign equalsign not-slash) articleid = 8
slash /
(not-equalsign equalsign anything) anothervar = abc
It replaces the last slash with an ampersand, and after looping, turns it into the first draft above: http://www.example.com/page/article/single/articleid=8&anothervar=abc . The third rule handles this as described above.
A note: These also assume all your urls will look like this, since they're going to tack on .htm to everything. If you want still allow explicit /something/page.htm then these rules would need to not-match on .htm if it's already there - something like that. Or maybe an initial rule up front that looks for .htm and just stops rewriting there. Or maybe only do this for the /page paths.

mod_rewrite Redirect Rule Variables question

I'm a bit of an .htaccess n00b, and can't for the life of me get a handle of regular expressions.
I have the following piece of RewriteRule code that works just fine:
RewriteRule ^logo/?$ /pages/logo.html
Basically, it takes /pages/logo.html and makes it /logo.
Is there a way for me to generalize that code with variables, so that it works automatically without having to have an independent line for each page?
I know $1 can work as a variable, but thats usually for queries, and I can't get it to work in this instance.
First you need to know that mod_rewrite can only handle requests to the server. So you would need to request /logo to have it rewritten to /pages/logo.html. And that’s what the rule does, it rewrites requests with the URL path /logo internally to /pages/logo.html and not vice versa.
If you now want to use portions of the matched string, you need to use groups to group them ( (expr)) that you then can reference to with $n. In your case the pattern [^/] will be suitable that describes any character other than the slash /:
RewriteRule ^([^/]+)$ /pages/$1.html
Try this:
RewriteRule ^/pages/(.*)\.html$ /$1
The (.*) matches anything between pages/ and .html. Whatever it matches is used in $1. So, /pages/logo.html becomes /logo, and /pages/subdir/other_page.html would become /subdir/other_page

Resources