Not Equal Condition for RewriteRule on .htaccess file - .htaccess

How to apply NOT EQUAL condition in inside RewriteRule statement.
For example, I want to call mypage.php file and pass an argument only when user not typed "test" data as a parameter. Other than "test" data system should call mypage.php by passing the given argument.
RewriteRule ^/?mypage/!(test)$ mypage.php?arg=$1 [L,NC]

You can use it like this :
RewriteRule ^/?mypage/((?!test).*)$ mypage.php?arg=$1 [L,NC]
((?!test).*) means Any characters zero or more times excluding test .

Related

.htaccess - Heal malformed url

I need a solution. For some reason in the past seems that I generate some "bad" links for bots only.
Resume: There is a fake "page" parameter when malformed url is present. When there are 2 "page" parameters then the first one is fake, must be removed.
X is random
Remove the parameter page only when "?/?page" is detected
Good: search?pagepage=496
Bad: search?/?page=X
Good: https://example.com/search?page=496
Good: https://example.com/search?page=496&orderBy=oldest
Bad: https://example.com/search?/?page=X&page=496&orderBy=oldest
RewriteCond %{QUERY_STRING} ^(.*)&?^XXX[^&]+&?(.*)$ [NC]
RewriteRule...
Thank you guys!
UPDATE
At final, I found a solution by myself:
RewriteCond %{QUERY_STRING} ^(.*)&?^/\?page=[^&]+&?(.*)$ [NC]
RewriteRule ^/?(.*)$ /search$1?%1%2 [R=301,L]
RewriteCond %{QUERY_STRING} ^/\?page=.+&(page=.*)
RewriteRule ^(search)$ $1?%1 [R=301]
This will do the rewrite for all your URLs that have the extra page parameter you want to keep.
To make the last part optional, we would have to wrap &(page=.*) into another set of braces, and add a ? as quantifier - (&(page=.*))?.
Then the back reference would need to be changed from %1 to %2 (because we only need that inner part, we don't want the &) - but then for your URL without any real page parameter to keep, there would be no match in this place, and therefor the %2 would not be substituted with anything, but added to the URL literally.
So better to leave the above as-is, and simply add
RewriteCond %{QUERY_STRING} ^/\?page=.+
RewriteRule ^(search)$ $1 [QSD,R=301]
below those two existing lines. The pattern does not need to be any more specific (because the URLs that have a genuine page parameter at the end, have already been handled by those previous two lines.) And the QSD makes it simply drop the existing query string, so that https://example.com/search?/?page=20 results in https://example.com/search (which I assume is what you wanted here, because there is no actual page parameter to keep, correct?)

Remove parentheses from the URLs query string in rewrite rule

I would like to clean up the URL's by removing parentheses from all query strings.
I tried the following code, but couldn't get it to work.
RewriteCond %{REQUEST_URI} [\(\)]+
RewriteRule ^(.*)[\(]+([^\)]*)[\)]+(.*)$ /$1$2$3 [R=301,L]
Here's an example of a URL:
http://www.example.com/blog/abc-post/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+blogname+(Blog+Name+New+York)
In order to match the query string you need to check the QUERY_STRING server variable in a RewriteCond directive.
Here are some ways of doing this:
1. Any number of parentheses - multiple redirects
For example, to remove any number of opening/closing parentheses in the query string part of the URL:
RewriteCond %{QUERY_STRING} (.*)[()]+(.*)
RewriteRule (.*) /$1?%1%2 [R,NE,L]
The NE flag is required in your example to avoid the %-encoded character (ie. %3A) being doubly encoded.
This will, however, result in multiple redirects, depending on the number of "groups" of parentheses. In your example, this will result in two redirects, because there a two "groups" of parentheses (a single parenthesis in each "group").
2. Any number of parentheses pairs - multiple (but fewer) redirects
If the parenthesis are always in matching pairs, then you can specifically check for the opening/closing parenthesis and potentially reduce the number of redirects.
RewriteCond %{QUERY_STRING} (.*)\((.*)\)(.*)
RewriteRule (.*) /$1?%1%2%3 [R,NE,L]
In your example, this results in a single redirect because there is just a single pair of parentheses. But /abc?foo=(bar)&one=(two) would result in two redirects.
3. Any number of parentheses - single redirect
This method performs multiple internal rewrites to remove the parentheses, followed by a single redirect once all the parentheses have been replaced:
# Remove parentheses from query string
RewriteCond %{QUERY_STRING} (.*)[()]+(.*)
RewriteRule (.*) /$1?%1%2 [E=REPLACED_PARENS:1,NE,L]
# Redirect to "clean" URL
RewriteCond %{ENV:REDIRECT_REPLACED_PARENS} 1
RewriteCond %{THE_REQUEST} ^GET\ /(.*)\?
RewriteRule ^ /%1 [R,NE,L]
The first rule internally rewrites the request and sets an environment variable if a replacement is required.
The second rule checks for this environment variable (note that REPLACED_PARENS becomes REDIRECT_REPLACED_PARENS after the first rewrite) and ultimately redirects to the cleaned URL. The URL-path is grabbed from the initial request (contained in the THE_REQUEST server variable) to avoid inadvertantly redirecting to the directory index (eg. index.php) when a bare directory is requested (or front-controller is used).

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.

RewriteRule - only two directories and a file

I am trying to rewrite URLs through .htaccess and what I want is that a rule be taken into account only if the URL is like "www.mysite.com/basedir/directory/file.htm".
I don't want "www.mysite.com/basedir/file.htm" or "www.mysite.com/basedir/directory/directory/file.htm", I want the exact described structure. At the moment I am trying to do it with this:
RewriteRule ^(basedir)/([^/\.]+)/(.*)\.(htm)$ /template.php?&page=$3 [L]
but it doesn't work. It accepts any number of directories after basedir.
Thanks for your help
Your second match area needs to have a character exclusion like the first:
RewriteRule ^(basedir)/([^/\.]+)/([^/]*)\.(htm)$ /template.php?&page=$3 [L]
That way you don't allow additional slashes to be matched, only the two explicit slashes earlier in the pattern.
Also, what exactly are you trying to match with $3? You only need to use parentheses around things that you need to match. If $3 is supposed to match file.htm, then you could instead write:
RewriteRule ^basedir/[^/\.]+/([^/]*\.htm)$ /template.php?&page=$1 [L]
or if it should just match "file" then:
RewriteRule ^basedir/[^/\.]+/([^/]*)\.htm$ /template.php?&page=$1 [L]

Redirect HTTP request to file only if it exists

I'm trying to (internally) redirect a call like /server123/get_file.php?file=frame-38-227113.jpg to /server123/cache/2/2/7/227113/frame-38-227113.jpg.
Of course, only if that file actually exists. Otherwise it will need to go through the get_file script in order to fetch the file.
But I failed to create the correct rewrite rules.
What I have till now:
RewriteEngine On
RewriteCond %{REQUEST_URI} =/get_file.php
RewriteRule ^.*$ /server063/get_file.php [L]
RewriteCond %{QUERY_STRING} file=(frame-[0-9]+-([0-9])([0-9])([0-9])[0-9]+.jpg)
RewriteCond %{REQUEST_URI} ^/(server[0-9]+)/get_file.php
RewriteCond %6/cache/%2/%3/%4/%1 -f
RewriteRule ^.*$ /$6/$5/cache/%2/%3/%4/%1 [L]
But that doesn't work.
I'm hoping someone could give me some insight?
Also when trying to prevent endless looping here I tried using IS_SUBREQ, but that seems to not do much (as in: it always re-tries to loop).
I see 2 issues in your rules:
your groups and file name don't seem to match what you say you want. See the directory structure carefully, you seem to have a dir containing the full 6-digits id of the file, which you are not capturing;
the %N replacements only contain matches for the last RewriteCond statement (per documentation, see: http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewritecond); which means you cannot access matches over multiple RewriteConds.
I think with some environment variable magic, you might be able to do what you want in multiple statements, but given that your file names look safe, I think in your case, you can use the variable THE_REQUEST, which lets you access both the uri and the query string in one go like this:
RewriteCond %{THE_REQUEST} ^GET\ /(server[0-9]+)/get_file\.php\?file=(frame-[0-9]+-(([0-9])([0-9])([0-9])[0-9]+).jpg)
RewriteCond %{DOCUMENT_ROOT}/%1/cache/%4/%5/%6/%3/%2 -f
RewriteRule . %1/cache/%4/%5/%6/%3/%2 [L]
Beware: THE_REQUEST is not escaped!

Resources