Help with regular expression with mod_rewrite - regex

I have links like these that I want to change:
mypage.com?page=missions&id=5
mypage.com?page=hello
I tried to change them into easier links with this:
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^([^/]*)/([^/]*)$ /index.php?page=$1&id=$2 [L]
It works but if I want to access pages like (mypage.com?page=hello) I have to write:
mypage.com/hello/
and if I write without the slash in the end like this
mypage.com/hello
it doesn't work.
How do I fix it? :)

This should work:
RewriteRule ^([^/]*)(/([^/]*))?$ /index.php?page=$1&id=$3 [L]
This will make the slash optional by including it in an optional group (denoted by (...)?), along with the optional second half of the query string. Since this introduces a new group between the first and second (left parenthesis determines the order), we have to change the second backreference from $2 to $3.
If the logic becomes much more complex than this, it may be easier to split up the rules.

You could add a second rule that omits the second parameter and optionally the slash:
RewriteRule ^([^/]+)/?$ /index.php?page=$1
RewriteRule ^([^/]+)/(\d+)/?$ /index.php?page=$1&id=$2
This might work too:
RewriteRule ^([^/]+)(?:/(\d+))?/?$ /index.php?page=$1&id=$2
For SEO, you'll probably want to redirect requests missing the slash to the same address with a slash. Use RedirectMatch for that.

I read about the trailing slash with SEO (didn't know about it, thank you mathew!) and the final result was this:
RewriteRule ^([a-zA-Z0-9_-]+)/$ /index.php?page=$1 [L]
RewriteRule ^([a-zA-Z0-9_-]+)/([a-zA-Z0-9_-]+)/$ /index.php?page=$1&id=$2 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ http://www.mypage.com/$1/ [R=301,L]
So now I force it to have a trailing slash.

Related

how do I use rewriteRule in htaccess

I'm trying to redirect some urls to pretty urls and the thing is that I'm new to this so I can't seem to figure out what part I did wrong
this is the htaccess right now but the rewrite rule is not working.
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ -
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([.]+)/([.]+)$ index.php?search_categories%5B%5D=$1&search_location=$2 [QSA,L]
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Try this rule:
RewriteRule ^(.+[^/])/(.+)$ index.php?search_categories=$1&search_location=$2 [QSA,L]
In your rule you have: search_categories%5B%5D, may be a mistake while copy/paste I removed the %5B%5D even this is not the problem
^(.+[^/])/(.+)$ match category/location the rule [^/] is to not match the slash /
EDIT:
It can also simplified with just: ^([^/]*)/(.*)$
In your code [.]+ the dot match Any single character but brackets is used for range like [abc] will match a, b or c, so it will not work with just [.]+, also like I wrote before you have to not match the slash with [^/] this last one must be inside brackets, more here and Cheat Sheet
Test here

How to match quantifiers { 6, } in RewriteRules?

I did a rewrite rule matching document names that are 6 characters, and it succeeds.
RewriteRule ^document\/(.{6})\/?$ document/?name=$1 [NE,L]
Since I know documents are named only up to 12 characters, I added a maximum length quantifier. However, using this, it produces a 500 Server Error:
RewriteRule ^document\/(.{6,12})\/?$ document/?name=$1 [NE,L]
In fact, I'm getting the following results:
(.{6}) works
(.{6,}) faults
(.{6,7}) works
(.{6,8}) works
(.{6,9}) faults
and so on.
I should also mention that https://www.regexpal.com/?fam=109235 tells me there isn't anything wrong with my rule. However I'm still getting the 500 Server Error on use.
Thank you #emma, example URLs to be rewritten:
http://www.mywebsite.com/document/051201-22
http://www.mywebsite.com/document/051201-22/
I'm not quite sure how you'd like to write this RewriteRule. However, this tool might help you to first find an expression, then write and test a RewriteRule. I'm pretty sure, you can write it without using a quantifier. For example:
document\/([0-9]+)
would pass your exampled URLs.
Then, if you wish to only replace the first six digits to the name variable, you might want to write a RewriteRule similar to:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} mywebsite\.com [NC]
RewriteRule document\/([0-9]+) document\/?name=$1 [NE,L]
</IfModule>
For yes or no trailing slashes, these might work:
# No Trailing Slash Policy, if you wish no slash at the end of your URLs
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R] # <- for test, for prod use [L,R=301]
# Trailing Slash Policy, if you wish to have a slash at the end of your URLs
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1/ [L,R] # <- for test, for prod use [L,R=301]
I think you enter in a redirect loop with this setup.
Add a RewritCond to check that there is not a query string in the request
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^document/([^/]{6,12})/?$ document?name=$1 [NE,L]

htaccess RewriteRule regex

I have hundreds of these old links I need to redirect.
Here is one example:
/index.php?option=com_content&view=article&id=433:seventh-character-code-categories-and-icd-10-cm&Itemid=101&showall=1
to
/seventh-character-code-categories-and-icd-10-cm
Essentially I need to remove the /index.php?option=com_content&view=article&id=433: part.
I tried this but I am getting confused with the [0-9] and : parts, so the following does not work:
RewriteRule ^/index.php?option=com_content&view=article&id=[0-9]:(.*)$ /$1 [L,R=301]
Say you want to capture from after : to right before & in the query string you mentioned, then try this expression:
^[^\:]*\:([^\&]*)\&.*$
As #starkeen mentioned in comments, you got to check against the query string. This can be done using RewriteCond %{QUERY_STRING}
So if index.php is in the root folder:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^\/index\.php$
RewriteCond %{QUERY_STRING} ^[^\:]*\:([^\&]*)\&.*$
RewriteRule ^(.*)$ http://example.com/%1 [R=301,L]
Here's another example. This one is for a sub folder:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^\/pages\/index\.php$
RewriteCond %{QUERY_STRING} ^[^\:]*\:([^\&]*)\&.*$
RewriteRule ^(.*)$ /pages/%1? [R=301,L]
Also, notice the ? at the end of the url /pages/%1?, this prevents from re-attaching the query string.
Another thing, captured groups will be set to variables %{number} since set in the RewriteCond.
BTW, depending on your server's configuration, you may need to add the NE flag, like [NE,L,R=301] Plus test whether it is necessary to double escape the literal characters.
what is about direct approach. Skip all till semicolon, mach string till & and replace all with first much
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{QUERY_STRING} [^:]+:([\w-]+[^&]).*
RewriteRule .*$ \/%1? [R=301,L]
</IfModule>

mod_rewrite trailing slash for directory and remove for file url

Ok. I got this problem I trying to remove the last slash in a file url for example http://domain.com/styles/styles.css/. I got the code for adding slash to the end but cannot figure how to do the conditional.
If the URL has an extesion then remove end slash
else add slash..
Here what I got right now some blogs says its the solution but still isn't working for what I expect.
RewriteCond %{REQUEST_URI} !\.[^./]+$
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)([^/])$ http://%{HTTP_HOST}/$1$2/ [L,R=301]
Also a problem, when I type http://domain.com/index it goes to http://domain.com/inde/.
Need your help guys.. Thanks a lot in advance.
add following code in your htaccess, for better understanding.
RewriteCond %{HTTP_HOST} !^\.yourdomain\.com$ [NC]
RewriteRule ^(.+)/$ http://%{HTTP_HOST}/$1 [R=301,L]
I have a link : domain.com/folder/
it will change to : domain.com//folder
also You can turn off mod_dir's redirect by including a DirectorySlash Off.
Why do you want to do an external redirect for such "furniture" files? Surely an internal redirect is what you want here?
Options -MultiViews
RewriteCond %{REQUEST_URI} !-d
RewriteRule ^(.+)/$ $1 [L]
I advise that you turn off mutliviews if you don't use it as this can generate subrequests which confuse things.
Your RewriteCond conditions are logically inverted because you have the ! operator there. So the rewrite is applying only for those inputs which do not have extensions, and which do not have a trailing slash!
You can do this with a single rule with no conditions:
# Match any sequence of characters, ending in a dot followed
# by one or more characters that don't contain dots or slashes,
# followed by a final trailing slash.
#
# Rewrite this absolutely and treat as redirect.
RewriteRule ^(.*\.[^./]+)/$ /$1 [L, R=301]

.htaccess regular expression need to make trailing forward slash optional

I need to include an optional trailing forwardslash, that's an /, in my RewriteRule
What I have so far is
RewriteRule ^([a-zA-Z0-9]+)$ u.php?$1|$2
Which works fine, for example http://foo.bar/abcde will redirect to http://foo.bar/u.php?abcde and handles any querystring parameters that may be present.
What I need to do is take http://foo.bar/abcde/ (with the trailing forwardslash) and redirect to http://foo.bar/u.php?abcde
So, if its present, I need remove the final forward slash from $1 in my RewriteRule. How do I do this? I'm new to apache and have tried many different regex rules but can't get it right.
Just put /? before the $ at the end in your pattern:
RewriteRule ^([a-zA-Z0-9]+)/?$ u.php?$1
But I would rather suggest you to allow just one spelling (either with or without trailing slash) and redirect the other one:
# remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ /$1 [L,R=301]
# add trailing slash
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .*[^/]$ /$0/ [L,R=301]