htaccess rewrite rule for Forbidding urls - .htaccess

I'm not really new to htaccess rewrites, but today I have seen a rule which I've not seen before:
# Access block for folders
RewriteRule _(?:recycler|temp)_/ - [F]
This rule is part of the Typo3 htaccess file.
What does the "?:" mean? Is this some kind of back reference? And what do the underlines stand for?
Many thanks!

Rule RewriteRule _(?:recycler|temp)_/ - [F] could be divided into 2 rules for better understanding. like:
RewriteRule _recycler_/ - [F]
AND
RewriteRule _temp_/ - [F]
Now let us understand what does that mean:
You could see its a shortcut method to make 1 rule out of 2 rules.
We could use regex to match multiple patterns and perform same kind of action on URIs which are falling in same criteria(which is matched by regex).
In this case we are trying to match _(literal character) followed by (?:recycler|temp). Where ?: stands up for a non-capturing group. So whatever comes into this section(?:.......) will NOT come in backreference capability. Its basically matching string/text recycler OR temp in regex which is preceded and followed by _
Now comes what is capturing group: in .htaccess we can use capability of capture matched values which we can use them later eg--> $1 for getting 1st captured value(stored in memory), we could say non-capturing group tells that we want to match a regex but DO NOT store that into memory(because we DO NOT want to use it later onwards into our program).
Here is an example of capturing group rules in htaccess rules:
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f [NC]
RewriteRule ^(first|second)/(.*)?$ $1.php?$2 [QSA,NC,L]
Explanation of above example: Its simply makes 2 capturing groups, 1st will have either first OR second, 2nd capturing group will have anything(because of we used .*) in it, so while rewriting part we are using $1 and $2 to get there values. You could clearly see that we could use these values in condition part as well(which becomes in backend like: %{DOCUMENT_ROOT}/first.php OR %{DOCUMENT_ROOT}/second.php).
Here is an example of non-capturing groups in htaccess Rules:
RewriteEngine ON
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f [NC]
RewriteRule ^(?:first|second)/(third/fourth)/?$ $1.php [QSA,NC,L]
Explanation of above example: We could see that we are matching first OR second in rule side so now value of $1 will be either third OR fourth this time since we used non-capturing group for first/second. So backend condition check will become like: %{DOCUMENT_ROOT}/third.php OR %{DOCUMENT_ROOT/fourth.php

Related

htaccess rewriterule generating multiple copies of wrong match

Trying to use prettyURLs rewritten to php param qrys using .htaccess rules.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^foo/?([^/]*)/?([^/]*)/?$ /foo.php?s=$1&c=$2 [NC,END,R=301,QSA]
RewriteRule ^bar/?([^/]*)/?$ /bar.php?s=$1 [NC,END,R=301,QSA]
The first rule works correctly, but the second one generates:
https://example.com/bar.php?s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=.php&s=45843
from
https://example.com/bar/45843
RewriteCond directives are only applied to the single RewriteRule immediately following them. That means that your second RewriteRule is not covered by any RewriteCond. Which means it creates an endless rewriting loop.
You want to reject that, pointing out that you rewrite to /bar.php which is not matched again by the matching pattern maybe, but ...
That is not true actually. Take a closer look at your rule:
RewriteRule ^bar/?([^/]*)/?$ /bar.php?s=$1 [NC,END,R=301,QSA]
The matching pattern uses /? which makes the slash optional . So bar.php?s=whatever is again matched. In the next round the rewriting engine does.
Solution:
apply the conditions to both rules and
use a proper matching pattern.
Actually I am not sure what you are trying to match with those patterns ... Why the /??
Are you trying to match a query string that way? That won't work, you need another RewriteCond for that applyiong a matching pattern against %{QUERY_STRING}. That is documented, actually.
Or are you trying to make anything after /bar optional ? Then use a pattern like ^/?bar(/[^/]*)?/?$ maybe ...

.htaccess rewrite rule case sensitive

I have the following rewrite rule:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/.]+)/?$ /pages/acticle.$1.php [L]
Currently it is case sensitive. I need to remove this restriction. I've tried changing [L] to [NC,L] but it didn't work. What am I missing?
Your pattern doesn't contain any cased characters, so adding NC will have no effect. If your RewriteRule was for ^abcde and you wanted it to also match ABCDE then adding NC to the rule would do this.
The pattern in your example matches any character that is not a . or / one or more times, and then adds it to the article.$1.php result. By default it will take whatever is matched directly so abc=article.abc.php, ABC=article.ABC.php, and so on.
I'm guessing that all of your article file names are in lowercase and that you want to rewrite ABC and AbC to abc, resulting in consistent naming for the files - both get article.abc.php. If so, there are a few options listed on this page - use a loop in .htaccess to replace uppercase with lowercase before continuing, use a RewriteMap in your http.conf, or use mod_speling.

Dynamically load subdomains folder as root with .htaccess

I'm trying to achieve, using .htaccess, so I can access all my projects with the configurations of one virtual host setup, and one URL defined in the hosts file. This will allow me to drop a project in the folder and it will function without having me to do any other configurations, and save a lot of time while working.
Example A: prestige.projects.dev is hosted on D:/projects/prestige etc.
Example B: newproject.projects.dev is hosted on D:/projects/newproject etc.
The code below works for the specific situation of Example A, but I can't figure out how to make it work 'dynamically' for all projects. My goal is to make prestige a wildcard. For example: newproject.projects.dev should automatically load the contents of D:/projects/newproject.
RewriteEngine On
RewriteCond %{HTTP_HOST} ^prestige\.projects\.dev$
RewriteCond %{REQUEST_URI} !^/prestige/
RewriteRule (.*) /prestige/$1
I'm open to other suggestions than this method, as long as the goal is achieved.
Try something like the following instead:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^([a-z]+)\.projects\.dev [NC]
RewriteCond "%{REQUEST_URI} /%1" !^(/[^/]+)[^\s]*\s\1$
RewriteRule (.*) /%1/$1 [L]
%1 is a backreference to the captured group in the last matched CondPattern.
The second RewriteCond directive is the "wildcard" version of your hardcoded check to make sure the REQUEST_URI does not already start with the directory that matches the subdomain - thus preventing a rewrite loop.
The string %{REQUEST_URI} /%1 (which expands to a string of the form "/<directory>/<anything> /<subdomain>" after the first rewrite) is matched against the regex ^(/[^/]+)[^\s]*\s\1$, which checks to see if /<directory> is the same as /<subdomain (\1 being an internal backreference to the captured group in the regex). Only if this does not match then the RewriteRule substitution occurs - in the same way your current rule works.

Can I combine these 3 rewrite rules into 1?

I'm having a brain fade and need some help please. I'm using 3 RewriteRules to accomplish something that I think should take just one:
RewriteRule ^([0-9]+)$ /bar/$1.html [R=301,L]
RewriteRule ^([0-9]+)(-*)$ /bar/$1.html [R=301,L]
RewriteRule ^([0-9]+)-([0-9]+)$ /bar/$1.html#$2 [R=301,NE,L]
I need to take the following URLs:
http://foo.com/100
http://foo.com/100-1
http://foo.com/200-
http://foo.com/1999
http://foo.com/1999-99
...and rewrite them like this:
http://foo.com/bar/100.html
http://foo.com/bar/100.html#1
http://foo.com/bar/200.html
http://foo.com/bar/1999.html
http://foo.com/bar/1999.html#99
What I have works but seems like a bit of a hack. is there a way to combine this all in to one rule?
I don't see a way to combine all three rules into a single rule, because the replacement structure is not always the same, with hash sometimes appearing and sometimes not appearing. But you can combine the first two rules:
RewriteRule ^([0-9]+)-?$ /bar/$1.html [R=301,L]
The second rule, which replaces with a hash symbol, can remain as is:
RewriteRule ^([0-9]+)-([0-9]+)$ /bar/$1.html#$2 [R=301,NE,L]
You can combine all 3 rules into one with this trick:
RewriteCond %{REQUEST_URI} ^/(\d+)-?(\d+)?$
RewriteCond %1#%2 ^(\d+)#$ [OR]
RewriteCond %1#%2 ^(\d+)(#\d+)$
RewriteRule ^ /bar/%1.html%2 [R=301,L,NE]
In the first condition, we match regex pattern that starts with a number followed by an optional hyphen and another optional number.
Next two conditions are using [OR] so only one will be true.
For URI /100, first condition will be true and 100 will be captured in %1 but %2 will be empty.
For URI /100-1, second condition will be true and 100 will be captured in %1 but %2 will be #1.

URL mod-rewriting

I want to mod_rewrite this Url:
Before:
website.altervista.org/page.php?name=value
After:
website.altervista.org/value
Solution:
RewriteCond %{REQUEST_URI} !page.php$
RewriteRule ^(.+)$ /page.php?name=$1 [L]
Explanation:
The mod_rewrite RewriteRule has 3 parameters:
Pattern
Substitution
Flags
Implemented as such:
RewriteRule pattern substitution [flags]
Starting at server root, enter the requested URL path in the RewriteRule "pattern" parameter, and the desired path in the "substitution" parameter. In this case:
RewriteRule ^(.+)$ /page.php?name=$1 [L]
If the URL varies and you don't want to (or can't) write a rule for every situation then use the regular expression ^(.+)$ to capture the dynamic value and inject it into your substituted path using the RE capture variable $1. The first set of parenthesis is $1, the second set is $2, etc. And capturing parenthesis can be nested.
^(.+)$ This regular expression can be read as: ^ at the start of the string, $ all the way to the end of the string, look for . any character + one or times and () capture that value into a variable.
Problem:
Even though we have the flag [L] (last rule evaluated), the mod_rewrite engine (behind the scenes) sends the newly constructed request /page.php?name=somevalue back through the mod_rewrite engine until no rules are met or, apparently, there are no changes to the request. Fortunately there is a supplimentary directive to expand on the conditional power provided by the RewriteRule called RewriteCond.
The mod_rewrite RewriteCond applies to the next occurring RewriteRule and also has 3 parameters:
Test String
Conditional Pattern
Flags (optional)
The Test String can be derived from a few sources. Often a Server Variable, relating to the current request, is used here as the subject of this condition.
The Conditional Pattern is, again, text or a regular expression, but has some additional special conditions that may be evaluated. Read the Apache online mod_rewrite documentation for a detailed explanation.
In this case: RewriteRule ^(.+)$ /page.php?name=$1 [L], our newly substituted request is sent back through mod_rewrite as /page.php?name=somevalue and matches our "catch-all" rule, therefore our original "somevalue" is lost and replaced with our newly requested resource page.php. To prevent our "catch all" from catching our "page.php" requests let's exclude it from the rule using RewriteCond.
RewriteCond %{REQUEST_URI} !page.php$
RewriteRule ^(.+)$ /page.php?name=$1 [L]
This RewriteCond can be read as: %{REQUEST_URI} get the requested resource and does it ! NOT $ end with page.php. If this condition is true, continue to the next condition or rule. If this condition is not true, skip this rule set and continue to the next rule set.

Resources