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.
Related
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 ...
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
I am new to .htaccess and I don't understand it well. Recently I have built the following code:
RewriteEngine On
RewriteCond %{HTTP_HOST} (.*)
RewriteCond %{REQUEST_URI} /api/v2/
RewriteRule ^api/v2(.*) /api/v2/api.php?input=$1
This was in the root public folder (example.com/.htaccess). But now I have to create second Rewrite and I want to make .htaccess file in example.com/api/v2/ folder. I tried to remove /api/v2/ part in each Rewrite Rule, but only thing I got was error 500.
What I want to achieve:
If someone uses this link: https://example.com/api/v2/test/test/123, I'd like to make it into https://example.com/api/v2/api?input=test/test/123 with .htaccess located in example.com/api/v2 folder.
Addressing your existing rule first:
RewriteCond %{HTTP_HOST} (.*)
RewriteCond %{REQUEST_URI} /api/v2/
RewriteRule ^api/v2(.*) /api/v2/api.php?input=$1
The first RewriteCond (condition) is entirely superfluous and can simply be removed. The second condition simply asserts that there is a slash after the v2 and this can be merged with the RewritRule pattern. So, the above is equivalent to a single RewriteRule directive as follows:
RewriteRule ^api/v2(/.*) /api/v2/api.php?input=$1 [L]
This would internally rewrite the request from /api/v2/test/test/123 to /api/v2/api.php?input=/test/test/123 - note the slash prefix on the input URL parameter value.
However, unless you have another .htaccess file in a subdirectory that also contains mod_rewrite directives then this will create a rewrite loop (500 error).
Also note that you should probably include the L flag here to prevent the request being further rewritten (if you have other directives).
If someone uses this link: https://example.com/api/v2/test/test/123, I'd like to make it into https://example.com/api/v2/api?input=test/test/123 with .htaccess located in example.com/api/v2 folder.
I assume /api? is a typo and this should be /api.php?. Note also that the slash is omitted from the start of the URL parameter value (different to the rule above).
I tried to remove /api/v2/ part in each Rewrite Rule, but only thing I got was error 500.
This is the right idea, however, you need to be careful of rewrite loops (ie. 500 error response) since the rewritten URL is likely matching the regex you are trying to rewrite.
Try the following instead in the /api/v2/.htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_URI} !api\.php$
RewriteRule (.*) api.php?input=$1 [L]
The preceding RewriteCond directive checks that the request is not already for api.php, thus avoiding a rewrite loop, since the pattern .* will naturally match anything, including api.php itself.
You could avoid the additional condition by making the regex more specific. For example, if the requested URL-path cannot contain a dot then the above RewriteCond and RewriteRule directives can be written as a single directive:
RewriteRule ^([^.]*)$ api.php?input=$1 [L]
The regex [^.]* matches anything except a dot, so avoids matching api.php.
Alternatively, only match the characters that are permitted. For example, lowercase a-z, digits and slashes (which naturally excludes the dot), which covers your test string test/test/123:
RewriteRule ^([a-z0-9/]*)$ api.php?input=$1 [L]
Or, if there should always be 3 path segments, /<letters>/<letters>/<digits>, then be specific:
RewriteRule ^([a-z]+/[a-z]+/\d+)$ api.php?input=$1 [L]
I've got a rewriterule in my .htaccess which allows me to add unlimited parameters separated by /'s.
RewriteRule ^(.*)/?$ index.php?params=$1 [L,NC]
This works properly untill I send an urlencoded string to it (using cURL) with an encoded \n in it (%0A).
So server/param1/param2/param3text works, but server/param1/param2/param3text1%0Aparam3text2 doesn't.
I found one Q on Stack Overflow mentioning a similar problem:
How can I apply an htaccess rewrite rule to a URL containing a linefeed character (%0A)?
But I can't/don't know how to implement [\r\n] in my (.*).
Any help?
Ok, so first, I had to add a check to make sure that the file didn't exist (the two RewriteCond's take care of that). Then I had to create a pattern that matched any character, or a \r or a \n that was matched one or more times(+). The zero or more times operator (*) didn't return the results properly.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^((.|\r|\n)+)/? index.php?params=$1 [L,NC]
Just an FYI here: A common hacking method called Whitespace filtering uses %0A
Filtering can be bypassed on the space character by using alternative
whitespace characters to the space character (%20). Most SQL engines
consider a line return (%0a in a *NIX environment, %0a%0d in a Windows
environment), tab characters, or the + character as valid whitespace:
You must utilize %{THE_REQUEST} variable to grab actual path from original Apache web server request.
Try this code:
RewriteCond %{QUERY_STRING} !^params=.+ [NC]
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+[^/]+/([^\s]+) [NC]
RewriteRule ^ index.php?params=%1 [L,QSA]
Then inside index.php check $_SERVER["QUERY_STRING"] for the full unadulterated path with %0A in it.
Well lets say I have this follow code in my htaccess file,
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.(.*) [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,NC,L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)$ $1.php
RewriteRule ^forums/([0-9]+) forums.php?category=$1 [NC]
I was wondering how would I, with the above code, redirect certain extensions in a url to my websites 404 page.
For instance, if this link mywebsite.com/forums has any extension at the end of it such as .asp, .php, .html, and so forth it then would get redirected to my 404 page.
And on a quick side note how can I limit the last RewriteRule to only a certain forward slash where mywebsite.com/forums/2 would show the page fine and anything after that certain limit such as mywebsite.com/forums/2/so on... would be redirected to my 404 page.
Anyone have any ideas?
If I understand the question properly, then you need to firm up the regular expressions to only match the patterns you really want - at the moment, they're a bit too lenient for your needs.
For example:
RewriteRule ^([^/]+)$ $1.php
This will match anything without a trailing slash, whereas if you wanted to restrict it to only match, say, things without a trailing slash and consisting of alphanumeric characters, then you might do this:
RewriteRule ^([a-zA-Z0-9]+)$ $1.php
(You could achieve the same effect for certain extensions only by using a lookahead assertion, but that complicates your regular expression. I feel it's probably saner (and easier on the mind) to think about the patterns you really want matched, and then express those up-front.)
Likewise, your latter example:
RewriteRule ^forums/([0-9]+) forums.php?category=$1 [NC]
will match anything which starts with the string forums/, followed by one or more digits, whether or not there's anything after that. Adding an end anchor ($) as you have above
RewriteRule ^forums/([0-9]+)$ ...
will assert that the string ends after the digits.
This relies on the fact that if mod_rewrite can't find a match, it won't attempt any rewrites, and will (in the absence of any explicit resource at that path) fall through to Apache's 404 handling, which is then up to you to override.