Does this RewriteRule require the `^` and `$` anchors? - .htaccess

I've seen the following RewriteRule in multiple tutorials.
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
My question regards the matching pattern:
^(.*)$ - Match anything but make sure "anything" is preceded by the start of the line and followed by the end of the line. 🤷‍♂️
(.*) - Match anything
The ^(.*)$ matching pattern seems to be unnecessarily verbose. Isn't (.*) sufficient?
(I've learned my lesson the hard way that RewriteRules are hard to test so I figured it was worth asking to make sure I'm not missing something obvious)

Not just ^ and $ are not needed even group (.*) is not needed here since you're not using $1 in target.
You can very well write your rule as:
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]
which is equivalent of:
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE]

Related

.htaccess RewriteRule to remove ? following hostname

I have an htaccess file with some rules, and I now want to add another rule which strips a part of the URL such that
www.mydomain.com/?generations/anything
becomes
www.mydomain.com/anything
(and anything means any other characters). I can make it work without the ?, but I can't seem to match/remove the ?. I tried:
1 failed:
RewriteRule ^\?generations/(.*)$ /$1 [L]
2 failed:
RewriteCond %{QUERY_STRING} ^generations/(.*)$
RewriteRule ^generations/(.*)$ $1 [L]
3 failed:
RewriteCond %{QUERY_STRING} ^generations/(.*)$
RewriteRule ^([^?]*)?generations/(.*)$ $2%1 [L]
4 failed:
RewriteRule ^([^?]*)?generations/(.*)$ $1$2 [QSA,L]
Can someone create a working rule - and explain why my third attempt above is not working? I can potentially see problems with the first two, but the third and fourth should work...
You're getting there with 3, but the query string is not included in a RewriteRule match. So you just want to match the empty string:
RewriteCond %{QUERY_STRING} ^generations/(.*)$
RewriteRule ^$ %1? [L]
But you also have it the wrong way round I think, if you want /anything to be the URL that is visited in the browser. You actually want just this:
RewriteRule ^(.*)$ ?generations/$1 [L]

htaccess replacing underscores with hyphens

Is there a more efficient way to doing this?
The last /(.*)$ is an ID that I don't care to use. only whats before it.
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6-$7-$8-$9-$10 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6-$7-$8-$9 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6-$7-$8 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6-$7 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5-$6 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4-$5 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3-$4 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2-$3 [NC]
RewriteRule ^about-us/news-room/(.*)_(.*)/(.*)$ index.php?go=/news/press-releases/$1-$2 [NC]
I found some solutions online but seem to get really confused on using the [N] flag? Not too sure here. Can anyone explain a better more efficient way to do this?
You can just let the rewrite engine loop internally for this:
RewriteRule ^about-us/news-room/(.+)/(.*)$ index.php?go=/news/press-releases/$1 [L,NC]
RewriteCond %{QUERY_STRING} ^go=/news/press-releases/(.*)_(.*)$
RewriteRule ^index\.php$ /index.php?go=/news/press-releases/%1-%2 [L]
The first rule sends the request to index.php, and the second rule removes the underscores and replaces them with dashes. Because the rewrite engine loops, it'll keep applying the rule until either the recursion limit is reached or all the underscores are gone.

Two rewrite rules don't cooperate

I'd like to rewrite two things on one site.
mysite.com/something -> mystie.com/index.php?s=something
and
mysite.com/something/another -> mysite.com/index.php?s=something&d=another
This is my htaccess
RewriteEngine on
RewriteRule ^(.+)$ index.php?s=$1 [L,QSA]
RewriteRule ^(.+)/(.+)$ index.php?s=$1&d=$2 [L,QSA]
Separately both work but together they don't...
I'm guessing the problem is that you're matching the '/' character in your first rule. Wouldn't the easiest solution be to simply add a character class to your rules, like:
RewriteRule ^([a-z0-9]+)$ index.php?s=$1 [L,QSA]
RewriteRule ^([a-z0-9]+)/([a-z0-9]+)$ index.php?s=$1&d=$2 [L,QSA]
or simply change the order of the rules:
RewriteRule ^(.+)/(.+)$ index.php?s=$1&d=$2 [L,QSA]
RewriteRule ^(.+)$ index.php?s=$1 [L,QSA]
Reverse the two rules. The rewrite engine goes through the file line by line, sequentially. The first rule you have:
RewriteRule ^(.+)$ index.php?s=$1 [L,QSA]
matches a url that has two name value pairs as well, so the file stop processing after the first match because you are using the L flag.
RewriteRule ^(.+)/(.+)$ index.php?s=$1&d=$2 [L,QSA]
RewriteRule ^(.+)$ index.php?s=$1 [L,QSA]
I don't have time to test this for you, sorry. But I'm feeling strongly that this is the problem. While I was writing this answer, someone gave pretty much the same advice. I thought of deleting my answer but want to make sure that you understood about the L flag and that the file is processed sequentially.
RewriteEngine on
RewriteRule ^([a-z0-9]+)$ index.php?s=$1 [L,QSA]
RewriteRule ^([A-Za-z0-9]+)/(.+)$ index.php?s=$1&d=$2 [L,QSA]
This works. Changing order didn't work. Also I forgot add that
mysite.com/something/another
the another string can be like asd-1231-ASDwqda .

Is it possible to have nested ReWrite Conditions in htaccess?

I have the following situation where I want to have nested ReWrite Conditions, and I have come across a situation where I am not able to see a proper documentation for the same.
RewriteCond %{REQUEST_URI} ^(robots.txt|favicon|ico)$ [NC]
RewriteRule . - [S=3]
# Nested ReWrite Condition
RewriteCond %{HTTP_HOST} ^www
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI_1} [R=301,L]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI_2} [R=301,L] # and so on
Therefore, the question comes up that whether the number of skip rules will comprise of the nested ReWrite Conditions, that is, in this case, should the number of skipped rewrite rules be 4 or 5(if including the rewrite condition).
RewriteCond %{REQUEST_URI} ^(robots.txt|favicon|ico)$ [NC]
RewriteCond %{HTTP_HOST} !^www
RewriteRule .* - [S=3]
# the following rules are run only if the first 2 conditions don't match
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI_1} [R=301,L]
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI_2} [R=301,L]
notice the ! negation in the 2nd cond
documentation:
This technique is useful because a RewriteCond only applies to the
RewriteRule immediately following it. Thus, if you want to make a
RewriteCond apply to several RewriteRules, one possible technique is
to negate those conditions and add a RewriteRule with a [Skip] flag.
Okay as you only have posted an example, I show you an example how it works. It's with comments, but if you still don't find it speaking enough, there is a lot more explanation available here.
# Does the file exist?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Create an if-then-else construct by skipping 3 lines if we meant to
# go to the "else" stanza.
RewriteRule .? - [S=3]
# IF the file exists, then:
RewriteRule (.*\.gif) images.php?$1
RewriteRule (.*\.html) docs.php?$1
# Skip past the "else" stanza.
RewriteRule .? - [S=1]
# ELSE...
Rewri
This should solve your issue. If not, please update your example in the question so it's clear what you're missing.
And yes, it skips Rules and not Conditions.

.htaccess - multiple parameters

I've been looking, at all of the same questions in here like my own: How to rewrite multiple parameters? And figured how to do, but it doesn't seem to work out very well for me.
I wan't my link to look like this: link.dk/profil/2/overview
And my .htaccess looks like this:
#profil.php?id=? to profil/?
RewriteRule ^profil/(.*)$ profil.php?id=$1 [L]
RewriteRule ^profil/(.*)/(.*)$ profil.php?id=$1&do=$2 [L]
It has to be able to access /profil/2 without the 3rd parameter. That's why I have 2 lines. I don't know if this is the right way to do it.
/profil/2 is working perfect and has been working for a while now. So no worries here. But I can't catch the 3rd parameter.
I'm also having those 2 in .htaccess file:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /.*index\.php\ HTTP/
RewriteRule ^(.*)index\.php$ /$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
Before the first two I wrote.
If I am using just the one with 2 parameters it's working. But then it's not working with /profil/2 ofc. And if I enter the url with profil.php?id=2&do=overview - I can access the page.
Found out my self:
RewriteRule ^profil/([^/]+)$ profil.php?id=$1
RewriteRule ^profil/([^/]+)/([a-z]+)$ profil.php?id=$1&do=$2
.* seems abit unprecise and unstable :-)

Resources