How to match quantifiers { 6, } in RewriteRules? - regex

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]

Related

String repeats 20 times in RewriteRule if i try to use it with $1, $2 etc. back-references. Weird. Why?

I try to do a RewriteRule redirect in .htaccess where the output URL has some additional text beside the captured text from the capture groups.
Original url: https://example.com/places/europe/hungary/budapest/
My regex pattern: ^places/([a-zA-Z-_]+/)?([a-zA-Z-_]+/)?([a-zA-Z-_]+/)?
i want to add a 'text-' string in the destination url around some $1, $2..
The full line in .htaccess: RewriteRule ^places/([a-zA-Z-_]+/)?([a-zA-Z-_]+/)?([a-zA-Z-_]+/)? https://example.com/places/$1text-$2$3 [R=301,L]
but it outputs exactly this:
https://example.com/places/europe/text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-text-hungary/budapest/
Instead of this: https://example.com/places/europe/text-hungary/budapest/
Yep, the additional 'text-' is repeating 20x times instead of 1.
If I don't put the 'text-' in the substitution string, all works as expected i.e:
https://example.com/places/$1$2$3 [R=301,L]
gives
https://example.com/places/europe/hungary/budapest/
What may cause this strange (to me) anomaly?
Is this should work without glitches or what is the correct syntax for this case?
All the other code in the .htaccess file (positioned after this RewriteRule part in question):
# BEGIN rlrssslReallySimpleSSL rsssl_version[3.3.5]
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTPS} !=on [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
</IfModule>
# END rlrssslReallySimpleSSL
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Yes it's a wordpress install.
Thanks a lot for any help!
As suggested in comments by Amit that you're running into this issue because pattern [a-zA-Z_-]+/ matches original string hungary as well as the target string text-hungary, thus results in a redirect loop.
You may use this rule with a negative lookahead to prevent a redirect loop as you're experiencing in your current rule:
RewriteRule ^places/([a-zA-Z_-]+/)((?!text-)[a-zA-Z_-]+/)([a-zA-Z_-]+/?)$ /places/$1text-$2$3 [R=301,L]
(?!text-) is a negative lookahead condition that will fail the match when $2 starts with text-.
Also note that an unescaped - should be placed at the start or end of a character class [...].
Make sure to clear your browser cache before testing this change.

Remove multiple trailing slashes in root using htaccess

I have a rule in my htaccess file to remove any extra trailing slashes from a url, this works on sub-directories with any more than 1 trailing slash. However it doesn't work on the root; which i need it to do.
For example.
http://www.example.com/test//// Redirects to http://www.example.com/test/
http://www.example.com/// Needs to redirect to http://www.example.com
Any ideas on what i need to add?. Cheers.
RewriteCond %{REQUEST_URI} ^(.*?)(?:/){2,}$
RewriteRule . %1/ [R=301,L]
For removing multiple slashes anywhere in REQUEST_URI this rule works best:
RewriteEngine On
RewriteCond %{THE_REQUEST} \s[^?]*//
RewriteRule ^.*$ /$0 [R=301,L,NE]
It takes advantage of the fact that mod_rewrite engine itself converts all multiple forward slashes to a single slash in the RewriteRule pattern. We use RewriteCond %{THE_REQUEST} to make sure original REQUEST_URI contains multiple slashes.
Here [^?]*// matches 2 // before matching query string since [^?] matches anything except ?. This will allow // in query string.
Try with:
RewriteCond %{REQUEST_URI} ^(.*?)//+$
RewriteRule ^ %1/ [R=301,L]
You htaccess works great as you can test on below link
https://htaccess.madewithlove.be/
So you need to make sure you test either with a Chrome Incognito window or using like below
curl -v http://example.com////
I usually prefer curl as I know it will give a fresh response from the server always
You just need two rule to match two different pattern
RewriteCond %{REQUEST_URI} ^(?:/){2,}$
RewriteRule . / [R=301,L]
RewriteCond %{REQUEST_URI} ^(.*?)(?:/){2,}$
RewriteRule . %1/ [R=301,L]

Rewrite rule in htaccess for nice links and I need advice

I'm trying to make nice links in my apps.
I decided to rewrite links that look like these:
1. http://example.cz/get1/get2/get3
2. http://example.cz
Into these (I have php appliactions only):
1. http://example.cz/index.php?path=get1+get2+get3
2. http://example.cz/index.php?path=
I'm removing www before links.
I keep failing to rewrite it into .htaccess.
I'm also looking for advice if the primary idea of rewriting get params into path=get1+get2+get3 is good? Right now I can see that link like this http://www.example.cz/you+me/ could possibly fail somewhere. Do you have any better solution?
So question is: How to rewrite it into .htaccess and how to solve possible problems with link that contains '+'
EDIT:
I improved my skills a little and I did this:
RewriteEngine on
Options +FollowSymlinks
RewriteCond %{HTTP_HOST} ^www\.(.+)$
RewriteRule (.*) http://%1/$1 [R=301,L]
RewriteCond %{REQUEST_URI} !^\/index.php(.*)
RewriteRule ^(.+) /index.php?path=/$1 [R=301,L] # 301 is here so I can see how does it work
# everything above works well (as I want)
# link now look like this one:
# http://example.net/index.php?path=/get1/get2/get3
# Now I was looking for universal rule that will rewrite my get params...
# First I did this:
RewriteCond %{REQUEST_URI} /([^/]+)
RewriteCond %1 !index.php(.*)
RewriteRule /([^/]+) $1+ [R=301,L]
# If any part of request uri is string that matches pattern /([^/]+)
# And if ([^/]+) doesn't match index.php(.*)
# then rewrite every /([^/]+) into $1+
# Now I see that it is incorrect, but I wasn't able to fix it
# So then I did different rule
RewriteRule ^([^=]+=[^\/]*)\/([^\/]+)(.*)$ $1$2+$3 [R=301,L]
# start of string
# first var is: one or more chars except =, =, zero or more chars except /
# /
# second var is: one or more chars except /
# third var is: zero or more chars
# end of string
I think second idea was much more better, but it doesn't work too. Please help me to fix it.
You can do this with the Apache module mod_rewrite. Chances are you probably already have it installed. Try this:
RewriteEngine On
RewriteRule ^([^/]+)/([^/]+)/([^/]+)/?$ index.php?path=$1+$2+$3 [L]
This regex assumes the URL will always contain three groups of text between slashes. You can tweak it as needed.
Also note that Apache never sees the URL hash, so you won't be able to match it in a rewrite rule. Luckily, it looks like you don't want to do anything with it anyway. Just use the rule above, and the hash will remain at the end of the URL in the browser.
I did solution. Problem was that after adding index.php?path= I wasn't able to work with query string...
The final universal solution that turn links from http://www.example.net/get1/get2/get3 to
http://example.net/index.php?path=get1+get2+get3:
RewriteEngine on
RewriteBase /
Options +FollowSymlinks
RewriteCond %{HTTP_HOST} ^www\.(.+)$
RewriteRule (.*) http://%1/$1 [R=301,L]
RewriteCond %{REQUEST_URI} !^\/index.php(.*)
RewriteRule ^(.+) /index.phppath=/$1 [R=301,L]
RewriteRule ^([^=]+=[^/]*)/([^/]+)(.*)$ $1$2+/$3 [R=301,L]
RewriteRule ^(.*)\+/+$ $1 [R=301,L]
RewriteRule ^(.*)path=(.*)$ $1?path=$2 [R=301,L]

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]

Help with regular expression with mod_rewrite

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.