I need to URL write uppercase URLs to lowercase.
I got that part working.
However, I am having problem. I am interested in excluding from the above *.html?vs=12312312
I tried the following:
RewriteCond %{REQUEST_URI} !^.*\.(html\?vs=) [NC]
But it didn't work.
http://foo.com/com.foo.bar/content/Any.html?vs=12312312
The above should stay the way it is, and not be rewritten.
What's wrong with the rule above? What should be the proper syntax?
Update
I tried the following:
RewriteCond %{REQUEST_URI} !(.*\.html\?vs=.*)$ [NC]
But still no luck.
The query string is not part of the REQUEST_URI, it is stored in QUERY_STRING. So try something like this, which goes before your existing rule:
RewriteCond %{REQUEST_URI} \.html$
RewriteCond %{QUERY_STRING} ^vs=[^&=]+$
RewriteRule ^ - [L]
The reason you need to do it this way (as its own separate rule), rather than putting an exclusion on your existing rule, is because you can't do AND with negative matches of RewriteCond, so putting them on your existing rule as negative matches would prevent it from running if only one applied (.html or ?vs=nnn). To reject when both apply, you need to do it in a separate, positive match like this.
If you have other rules you need to apply to those URLs after this, look at the [S=1] flag (documentation) which will skip the next rule on a match, instead of [L] which says stop processing here after a match (and hence don't apply your subsequent rules for these URLs).
The rule RewriteRule ^ - just says don't change anything, it's used to only apply the effect of the flags.
Related
I have a URL like this:
http://example.com/category/title which comes from the link http://example.com/cview.php?url=title
I want to create pagination and to be like http://example.com/category/title/page/1 or
http://example.com/category/title/1
this comes from http://example.com/cview.php?url=title&pageno=1.
I have tried this in .htaccess without success
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^category/([^/]*)$/([^/]+)/?$ /cview.php?url=$2&pageno=$1 [L]
Can anyone help please?
RewriteRule ^category/([^/]*)$/([^/]+)/?$ /cview.php?url=$2&pageno=$1 [L]
You have an erroneous $ (end-of-string anchor) in the middle of the RewriteRule pattern. You also appear to have the backreferences $1 and $2 the wrong way round. You are also allowing an optional trailing slash, yet your example URLs do not use this. (An optional trailing slash potentially creates a duplicate content issue.)
If you allow both /category/title/page/1 and /category/title/1 then you are potentially creating a duplicate content issue. Presumably you are only linking to one of these URL formats?
Since the page number is a "number" then it makes sense to just match numbers, rather than anything - this also helps to avoid conflicts with other directives.
It doesn't look like you need the conditions (RewriteCond directives) that check the request does not map to a file or directory, since I wouldn't expect a request of the form /category/title/page/1 to map to a file or directory anyway?
Try the following instead (without the RewriteCond directives):
RewriteRule ^category/([^/]+)(?:/page)?/(\d+)$ /cview.php?url=$1&pageno=$2 [L]
This matches both /category/title/page/<num> and /category/title/<num>. The optional subpattern (?:/page) is non-capturing, so that it doesn't mess up the numbering of the backreferences.
Bear in mind also that the order of the rules in .htaccess is important in order to avoid conflicts.
I supposed to have the following URLs to be converted to user-friendly format:
example.com/product/$numbers/$anychars => example.com/product.php?product_id=$numbers&name=$anychars
example.com/image/$numbers/$anychars/$number => example.com/image.php?image_id=$numbers&name=$anychars&no=$number
example.com/item/$numbers/$anychars => example.com/item.php?item_id=$numbers&name=$anychars
example.com/category/$anychars => example.com/category.php?name=$anychars
example.com/category/$anychars/$numbers => example.com/category.php?name=$anychars&page=$numbers
Trailing forward slash should be allowed and ignored by the web-server.
Using some guides from the Internet I did the following:
RewriteEngine On
RewriteRule ^product/([0-9]+)/([^/]+)/?$ product.php?id=$1&name=$2 [QSA,NC,L]
RewriteRule ^image/([0-9]+)/([^/]+)/([0-9]+)/?$ image.php?item_id=$1&item_name=$2&no=$3 [QSA,NC,L]
RewriteRule ^item/([0-9]+)/([^/]+)/?$ item.php?id=$1&name=$2 [QSA,NC,L]
RewriteRule ^category/([^/]+)/?$ category.php?cat=$1&page=0 [QSA,NC,L]
RewriteRule ^category/([^/]+)/([0-9]+)/?$ category.php?cat=$1&page=$2 [QSA,NC,L]
NC flag indicated to make it case insensitive.
L flag indicated to stop searching for match after one match was found (less bugs and faster URL handling)
Preliminary testing showed no errors.
But as regexps and mod_rewrite is not my best hobbies I'd like to ask you to check if I didn't make any errors. And if there's no - it could be a good pattern for a guys like me looking for a easy mod_rewrite solution.
There is one recommendation I would make. Put the rules in order from most specific match to most general match (in this case, switch the two category rules). By following this convention you ensure that a URL that may satisfy more than one rule is caught by the more specific rule.
In your specific case, you won't hit this problem yet, but as you grow your rules it will eventually bite you.
I haven't added QSA flags. I recommend that you create rules that would allow the user to see an entirely friendly URL, rather than a partly-friendly URL - to do this, ensure that you map additional parameters just like you have the ids and categories in your existing rules.
RewriteEngine On
RewriteRule ^product/([0-9]+)/([^/]+)/?$ product.php?id=$1&name=$2 [NC,L]
RewriteRule ^image/([0-9]+)/([^/]+)/([0-9]+)/?$ image.php?item_id=$1&item_name=$2&no=$3 [NC,L]
RewriteRule ^item/([0-9]+)/([^/]+)/?$ item.php?id=$1&name=$2 [NC,L]
RewriteRule ^category/([^/]+)/([0-9]+)/?$ category.php?cat=$1&page=$2 [NC,L]
RewriteRule ^category/([^/]+)/?$ category.php?cat=$1&page=0 [NC,L]
Currently, I have the rule
RewriteRule ^([A-Za-z0-9-/]+)$ myFile.php?myId=$1
I want to be able to access a folder and its files (lets just say it's called example), and the index.php of it. However, using the rule
RewriteRule ^example$ example/index.php [L]
it instead matches the first rule. It is the first rule of the file, though.
After your rewrite rules are executed, the example URL is rewritten to example/index.php, and then re-enters the rewrite process (the [L] flag does not prevent that). Then, your other rewrite rule matches.
So you must add an exception for example/index.php. For example:
RewriteRule ^example/index.php$ - [L]
which terminates the second rewrite run. Make sure to insert it above your other rule.
You could use a condition:
RewriteCond %{REQUEST_URI} !^/example
RewriteRule ^([A-Za-z0-9-/]+)$ myFile.php?myId=$1 [L]
This way you will get your rule match, unless request begins with '/example'. You may add extra slash, i.e. '/example/' to avoid un-matching '/example-page'.
So, I had a question earlier about mod_rewrite which you find here mod_rewrite changing /subpage/ to /subpage
But now I have a whole new problem with this... How do I make GET work?
Like if I need to pass some variables with GET, ex: mypage.com/subpage/?name=Jamie
My mod_rewrite looks like this:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^([A-Za-z0-9-]+)/?$ ?p=$1 [L]
I understand that the problem probably has to do with that I already pass and rewrite one GET request. So how do i tweak this to accept any other GET-request i might need to process?
UPDATE:
To clarify the problem a bit. If I try the url mypage.com/subpage/?name=Jamie page loads as if i used url mypage.com/subpage/ and "name" is never passed. Using my original url mypage.com?p=subpage&name=Jamie works as it should.
I guess i need to tweak this somehow... but how?
Thank you for taking your time reading my probably easy question!
Use the QSA flag — Query String Append:
RewriteRule ^([A-Za-z0-9-]+)/?$ ?p=$1 [L,QSA]
'qsappend|QSA' (query string append)
This flag forces the rewrite engine to append a query string part of the substitution string to the existing string, instead of replacing it. Use this when you want to add more data to the query string via a rewrite rule.
try
RewriteRule ^([A-Za-z0-9-]+)/\?$ ?p=$1 [L]
as '?' is a meta character in regex, it needs to be escaped
I finally figured out a good/easy way to make clean URLs with regex on my site in this format below, however it will require a very large .htaccess file, I know from the post on here that it is supposed to not be to bad on performance to use mod_rewrite but I have never really seen it used where the way I am, with a seperate entry for almost every page of my site.
Below is an example of an entry, there is 2 entries for 1 page, the first entry re-writes
http://www.example.com/users/online/friends/
to
http://www.example.com/index.php?p=users.online.friends
It works great but if the user is not on the first page then there is another thing added to the URL for paging and I had to write another entry to rewrite when this happens, is this the correct way or should these be combined somehow?
RewriteRule ^users/online/friends/*$ ./index.php?p=users.online.friends&s=8
RewriteRule ^users/online/friends/(\d+)/*$ ./index.php?p=users.online.friends&s=8&page=$1
The second one would do this
http://www.example.com/users/online/friends/22/
to
http://www.example.com/index.php?p=users.online.friends&page=22
It depends what you think is more readable, but here's how you could do it with a single rule:
RewriteRule ^users/online/friends(/(\d+))?/*$ ./index.php?p=users.online.friends&s=8&page=$2
(Edited to be more faithful to treatment of trailing slash in original question. Was: RewriteRule ^users/online/friends/((\d+)/*)?$ ./index.php?p=users.online.friends&s=8&page=$2)
Here I've just put "(...)?" around the final part of the url to make it an optional match, and changed the backreference to $2.
Of course, this actually rewrites http://www.domain.com/users/online/friends/ as:
http://www.domain.com/index.php?p=users.online.friends&page=
So your PHP code would have to check whether the page parameter is non-empty.
Yes, that's fine. I guess they could be combined into a single rule but there's not really any need.
You might consider leaving page as part of the URL so instead of:
http://www.domain.com/users/online/friends/22/
just have:
http://www.domain.com/users/online/friends?page=22
and then have one rule something like:
RewriteRule ^users/online/friends/?$ ./index.php?p=users.online.friends&s=8 [L,QSA]
to append the query string
Edit: There are a couple of ways of reducing the number of rewrite rules you have.
Firstly, use wildcards in the search terms, like:
RewriteRule ^users/(\w+)/(\w+)$ /index.php?p=users.$1.$2 [L,QSA]
will reduce quite a number of rules.
Secondly, if you're passing everything through /index.php just consider delegating all requests there:
RewriteRule ^(users/*)$ /index.php/$1 [L,QSA]
That rule uses a third technique: instead of passing the path information via a query string parameter, pass it via the extra path info. That can be accessed via $_SERVER['PATH_INFO'].
That being said, lots of rules isn't necessarily bad. At least it's explicit about all your actions. The thing you have to watch out for is creating a maintenance nightmare however.
# Initial step
RewriteCond %{QUERY_STRING} !(?:^|&)p=
RewriteRule ^([^/]+)/(.+) /$2?p=$1 [QSA]
# Subsequent steps
RewriteCond %{QUERY_STRING} ((?:[^&]*&)*?)p=([^&]*)(.*)
RewriteRule ^([^/]+)/(.+) /$2?%1p=%2.$1%3
# Last step with page number
RewriteRule ^(\d+)/?$ /index.php?page=$1 [QSA,L]
# Last step without page number
RewriteCond %{QUERY_STRING} (?:((?:[^&]*&)*?)p=([^&]*))?(.*)
RewriteRule ^([^/]+)/?$ /index.php?%1p=%2.$1%3 [L]
This would rewrite the URL in several steps:
http://www.domain.com/users/online/friends/22/
http://www.domain.com/online/friends/22/?p=users
http://www.domain.com/friends/22/?p=users.online
http://www.domain.com/22/?p=users.online.friends
http://www.domain.com/index.php?p=users.online.friends&page=22
An easier method would be the following, but would require you to change your scripts:
RewriteRule ^(.*?)(?:/(\d+))?/?$ /index.php?p=$1&page=$2 [QSA,L]
It would do everything in one step, with a little difference:
http://www.domain.com/users/online/friends/22/
http://www.domain.com/index.php?p=users/online/friends&page=22
Adding the s=8 query argument would require more work:
Creating a text-file with the menu numbers for each page.
Adding a RewriteMap directive.
Changing the second-last rule to use the same RewriteCond as the last rule has.
Adding &s=%{menumap:%2|0} to the last two rules.