RewriteRule match root dir? - .htaccess

There appears to be some historic confusion on existing answers in SO on the exact regex to use to match a request for the root directory. eg: ^/$ , ^$ or ^/?$
See the answers here and here.
So, let's clarify it
Question:
What is currently valid, 'for 2018' way to match a request to the root dir?
Single case test (with chrome)
I did run a quick test and it seems (with chrome at least) to always match ^$ regardless of how the url was typed, Including /?test. This last bit makes me think the server config matters too.
RewriteRule ^/$ /index-with-slash.html [L,R=301,NE] <-- no hits
RewriteRule ^$ /index-wo-slash.html [L,R=301,NE]

^/?$ will match both cases. No need to reinvent the wheel.
If you are concerned about regex being heavy on the resources, you likely would not be using Apache anyways.

Related

htaccess redirect "/?id=(.*)", but only at the root?

I have been unable to get a redirect to work. The behavior I was hoping to have would redirect from:
www.mysite.com/?id=12345
to
www.mysite.com/?other_id=12345
The rule I wrote seems to grab any url matching the very end like:
www.mysite.com/directory/another/?id=12345
I just want this to work at the root level, not all levels.
The rule I currently have is as follows:
RewriteCond %{QUERY_STRING} ^(.*&)?id=([^&]+)$
RewriteRule ^(.*)$ http://%{SERVER_NAME}/?other_id=%2 [R=301,L]
For some reason I had to include the first regex as it was not accepting it without it. Without the first ^(.*&) It kept saying that the site was creating a redirect that would not work and bombing out, which may be a part of my problem.
IS there a better way to write this rule? or is a root level match alone not possible?
Thank you,
Silvertiger
Change your regex from ^(.*)$ to `^$``:
RewriteCond %{QUERY_STRING} ^(.*&)?id=([^&]+)$
RewriteRule ^$ http://%{SERVER_NAME}/?other_id=%2 [R=301,L]
The ^(.*)$ regex matches any request URI, so /, and /foo and /dir1/dir2/dir3/file.txt will all match. But the ^$ only matches /.

.htaccess: Using domain name from RewriteCond

I've been googling the hell out of the problem I'm having and so far I have found nothing that works.
What I have is a Drupal multi-site installation that I'm trying to setup redirects for mobile on. To start I have 10 domains that have only one common string, www. What I want is to check if the device viewing the site is mobile (I'm using AMF to successfully do this) and make sure that the visitor is not already on the mobile version which will be m.domain.tld. If all is good then I need to redirect the user to the mobile subdomain.
Doing this per domain works using the following:
RewriteCond %{ENV:AMF_DEVICE_IS_MOBILE} ^true$
RewriteCond %{ENV:AMF_DEVICE_IS_TABLET} !^true$
RewriteCond %{HTTP_HOST} !^[m.]+mysite.com$
RewriteRule (.*) http://m.mysite.com/$1 [R=301,L]
I do not, however, want to have 10 of those blocks (1 for each domain) nor do I want to have to create another block every time we create a new website.
I have read that you can use () in the RewriteCond patterns to make a var out of the matching pattern. Unfortunately I don't think I'm making my pattern properly or something because when I try the following it redirects to m. followed by whatever the request uri is.
I'm leaving out the AMF conditions for brevity.
RewriteCond %{HTTP_HOST} !^[m.]+([^.]\.[com|net|org])$
RewriteRule (.*) http://m.%1/$1 [R=301,L]
From what I read, the %1 should match my pattern from the RewriteCond but it isn't matching anything. That makes me think my pattern is wrong. I've tried changing ([^.].[com|net|org]) to (.*) but get the same issue where it just redirects to m..
Am I right in assuming my pattern is wrong and if so what should I be using? Is what I'm trying to do even possible?
To be clear, my domains are in the form of:
www.domain.com
www.anotherdomain.net
somedomain.org
www.maybeanotherdomain.com
In my examples I have the flag R=301 but in testing I'm leaving that out and have to clear a lot of data from the browser each time I test to make sure I'm picking up the new rule.
Thanks in advance for any help!
You can't backreference a not match (!), but you can separate the condition into 2 matches against the %{HTTP_HOST} variable:
RewriteCond %{HTTP_HOST} !^m\.
RewriteCond %{HTTP_HOST} ([^\.]+)\.(com|net|org)$ [NC]
RewriteRule (.*) http://m.%1.%2/$1 [R=301,L]
You may need to tailor the ([^\.]+)\. bit to suit your needs, this expression will only match the "domain" part of "www.domain.com".

.htaccess mod-rewrite conditional statements and sending GET request?

Not necessarily a problem, just something that I am not yet knowledgeable enough to do. I have an .htaccess file that I am using for url rewriting. This is what I have now.
ErrorDocument 404 /inc/error_documents/404.php
ErrorDocument 503 /inc/error_documents/503.php
# For security reasons, Option followsymlinks cannot be overridden.
#Options +FollowSymLinks
Options +SymLinksIfOwnerMatch
RewriteEngine ON
RewriteRule ^home$ /index.php [nc]
RewriteRule ^(about|contact|giving-tree)/?$ /$1.php [nc]
RewriteRule ^giving-tree/([0-9+]?)/?$ giving-tree.php?ageBegin=$1 [nc]
RewriteRule ^giving-tree/([0-9+]?)/([0-9+]?)/?$ giving-tree.php?ageBegin=$1&ageEnd=$2 [nc]
RewriteRule ^giving-tree/([0-9+]?)/([0-9+]?)/([0-9+]?)/?$ giving-tree.php?ageBegin=$1&ageEnd=$2&page=$3 [nc]
What I want to be able to do is make some of the parts in the 3 bottom rules optional. I know that I can accomplish this with RewriteCond, but I'm not sure how. What I need is basically this:
RewriteCond %{HTTP_HOST} ^hearttohandparadise.org/giving-tree
RewriteRule /beginAge-([0-9+]) #make it send GET request with beginAge as the variable
RewriteRule /endAge-([0-9+]) \?beginAge=$1 #make it send GET request with endAge as the variable
etc... etc...
Is there any way to accomplish this just by relying on .htaccess? or am I just fantasizing?
Forgive me is I sound stupid.
No, it's a perfectly valid idea. You'd basically want to allow the user to write the URI in an unstructured manner, without a strict order imposed, right? Like, I could write giving-tree/page-6/endAge-23?
If so, this is what you're looking for:
RewriteRule /beginAge-([0-9]+) giving-tree.php?beginAge=$1 [QSA,NC]
RewriteRule /endAge-([0-9]+) giving-tree.php?endAge=$1 [NC,QSA]
RewriteRule /page-([0-9]+) giving-tree.php?page=$1 [NC,QSA]
You see, if any part of the URI matches the expression "/beginAge-([0-9]+)", it'll be redirected to giving-tree.php?beginAge=$1; the magic is done by the QSA, Query String Append, option, which, well, appends any existing query string to the resulting URI. So as more and more matches are found and more and more GET parameters added, the query string just grows.
If you want a stricter thing, where some parameters are optional, but their order is fixed, then it's uglier by magnitudes:
RewriteRule /(beginAge-)?([0-9]+)/?(endAge-)?([0-9]+)?/?(page-)?([0-9]+)? giving-tree.php?beginAge=$2&endAge=$4&page=$6 [NC]
I just made everything optional by using the ? operator. This one may use some prettifying/restructuring.
(Alternatively, you could just do this:
RewriteRule ^giving-tree/([^/]+)/?$ process.php?params=$1 [nc]
That is, grabbing the entire part of the URI after the giving-tree part, lumping the whole thing into a single parameter, then processing the thing with PHP (as it's somewhat better equipped to string manipulation). But the first version is certainly more elegant.)
By the way, are you sure about the ([0-9+]?) parts? This means "One or no single character, which may be a digit or the plus sign". I think you meant ([0-9]+), i.e. "one or more digit".

htaccess - Rewrite rule and/or condition to fix totally different discontinued or incorrect incoming link

Well, I am stuck again. Two days of reading and again, found some close solutions but, nothing fits and all my experiments failed.
This is a continuation of my question:
here at stackoverflow
The 4 rules below take my incoming links:
http://somedomain.com/getme.pl?dothis=display&partnum=1234567
and beatifies it.
Also allows users to use the beatified version right in address bar:
http://somedomain.com/1234567
Here are my working rules:
RewriteRule ^([\s]*)$ /getme.pl [L] ## in case there is a space or nothing.
RewriteRule ^([0-9]*)$ /getme.pl?dothis=display&partnum=$1&rewrite [L]
RewriteCond %{QUERY_STRING} partnum=([0-9]*)$
RewriteRule (.*) /%1? [L,R=301]
Works great but, I discovered there are some old links to the site out there:
http://somedomain.com/oldversion.php?id=123456789
And
http://somedomain.com/oldversion.php?r=86this&id=123456789
I would like to just grab the id=[0-9] and integrate it with my working rules.
I suppose, the rule would be inserted between the second and third rules above.
I tried various attempts (about 100!) like:
RewriteRule ^(oldversion\.php)?([a-z]{1})=([a-z0-9]*)&([a-z]{2})=([0-9]*)$ /$4? [L]
RewriteRule ^(oldversion\.php)?([a-z]{2})=([0-9]*)$ /$3? [L]
As you see, two days of reading and nothing is sinking in for me.
I tried several variations of the working rules I already have as well, to no avail.
Can't I just get the 123456789 off of the outdated .php urls somehow and stick it in my existing rules?
Thanks for your help and explaining down to my level co, I just might be able to understand...
Put this at the end of your .htaccess file:
RewriteCond %{QUERY_STRING} id=([^&]+)(&|$) [NC]
RewriteRule ^oldversion\.php$ /%1? [L,R=301,NC,NE]
For a URI of /oldversion.php?r=86this&id=123456789 it will internally redirect to /123456789
Remember RewriteRule just matches your URI and it cannot match your QUERY_STRING.

.htaccess mod_rewrite problem - shot myself in the foot?

I have a page called category.php5 that uses $_GET["category"] to fetch the right content from the database. I want to pretty it up so is looks like:
sinaesthesia.co.uk/category/psoriasis
which would equal:
sinaesthesia.co.uk/category.php5?category=psoriasis
I have successfully done this sort of rewriting before, but since I can't get it to work now, I'm worred that I might have rules in place that are somehow screwing me. Here is my entire .htaccess file - the last couple of lines are supposed to do the above rewrite:
RewriteEngine On
#remember to change this to aromaclear
RewriteCond %{HTTP_HOST} !^sinaesthesia\.co.uk$ [NC]
RewriteRule ^(.*)$ http://sinaesthesia.co.uk/$1 [R=301,L]
#Translate default page to root
RewriteCond %{THE_REQUEST} ^GET\ .*/index\.(php5|html)\ HTTP
RewriteRule ^(.*)index\.(php5|html)$ /$1 [R=301,L]
#translate any .html ending into .php5
RewriteRule ^(.*)\.html$ /$1\.php5
#change / for ?
RewriteRule ^(.*)\.html/(.*)$ /$1\.html?$2
#strip .html from search res page
RewriteRule ^(.*)search/(.*)$ /$1search_results\.html/search=$2
#translate product details link from search res page
RewriteRule ^products/(.*)/(.*)/(.*)$ /product_details.php5?category=$1&title=$2&id=$3 [L]
#Translate products/psorisis/chamomile-skin-cream-P[x] to productview.php5?id=1
RewriteRule ^products/.*-P([0-9]+) /productview.php5?id=$1 [L]
#Translate /category/psoriasis to /category.php5?category=$1
RewriteRule ^category/(.*) /category.php5?category=$1 [L]
When I manually enter category.php5/category=psoriasis, it works great. When I enter category.php5/category/psoriasis, it doesn't. I'm worried that my line that changes a html/ to html? is an error, however when I take that line out, it still doesn't work. Everything else works as expected.
As a general strategy, strip down your file by commenting everything out, then re-enable things piece by piece until you find the rule that causes it to break.
Bear in mind that browsers sometimes cache redirects, so starting a fresh browser instance is a good idea. A useful service is http://web-sniffer.net/ which will give you an uncached result.
In general, looking at your set of redirects, this seems a little convoluted to me because of the chaining/sieve -type system you seem to be using. Instead, I would recommend starting with URLs that can be identified specifically, e.g. starting with
RewriteRule ^category/(.*) /category.php5?category=$1 [L]
and then leaving the rather messy .html => .php conversion stuff towards the end, if you end up needing it at all. I've done a lot of sites using redirects and have never needed generic conversions like that, so they should be avoidable.
Also bear in mind that .* means matching anything or nothing, so you probably want to use .+ instead.
Ah: because I have a document called category.php5 and I'm trying to use category/psoriasis, the server tries to resolve that as category.php5/psoriasis, which fails. Fixed it now!

Resources