.htaccess skip all rules if url matches - apache

I want to skip all rewrite URLs when specific URL matches. I want to open this page:
https://www.example.com/.well-known/pki-validation/godaddy.html
If godaddy.html matches the URL. Here is what i am doing:
RewriteCond "%{REQUEST_URI}" "==/godaddy.html"
RewriteRule ^(.*)$ https://www.example.com/.well-known/pki-validation/godaddy.html [L]
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule ^(.*)$ https://www.example.com/index.php
but it does not work. I have also tried the [END] flag, but when I write flag [END] it gives me 500 internal server error.

If you want to stop rewriting, when the requested URL ends with godaddy.html, you can use a dash - as the substitution
Substitution of a rewrite rule is the string that replaces the original URL-path that was matched by Pattern. The Substitution may be a:
...
- (dash)
A dash indicates that no substitution should be performed (the existing path is passed through untouched). This is used when a flag (see below) needs to be applied without changing the path.
RewriteRule godaddy.html$ - [L]

Related

Rewrite that appends a query string is not firing?

I'd like to perform internal redirect
From /search/lalafa to /search/lalafa?post_type=review
The rule is
RewriteRule ^/search/([^/]+)$ /search/$1?post_type=review [L]
Seems correct but it doesn't seem to be matching:
https://htaccess.madewithlove.com/?share=c2ce1c7f-60be-40c8-9f0b-58ffc9eeba40
RewriteRule ^/search/([^/]+)$ /search/$1?post_type=review [L]
This will fail for two reasons:
The URL-path matched by the RewriteRule pattern in .htaccess does not include the slash prefix, so this rule never matches. It should be ^search/([^/]+)$.
If it did match it would create a rewrite-loop (500 Internal Server Error) since you are rewriting to the same URL-path and not checking the query string.
Try the following instead:
RewriteCond %{QUERY_STRING} !=post_type=review
RewriteRule ^search/[^/]+$ $0?post_type=review [L]
The $0 backreference contains the full URL-path, as matched by the RewriteRule pattern (NB: no slash prefix). The preceding condition checks that the query string is not already equal to post_type=review, thus preventing a rewrite-loop.

htaccess Redirect URL with GET Parameters

I have a URL that is in the format http://www.example.com/?s=query
I want to redirect this URL to http://www.example.com/search/query
I have the following .htaccess but I wanted to check if there is anything wrong with this. My RewriteRule looks a little wonky and I don't know if it will cause problems for other URLs.
RewriteEngine on
RewriteCond %{QUERY_STRING} ^s=(.*)$ [NC]
RewriteRule ^$ /search/%1? [NC,L,R]
I ran a test Here and it seems to redirect to the correct URL.
RewriteCond %{QUERY_STRING} ^s=(.*)$ [NC]
RewriteRule ^$ /search/%1? [NC,L,R]
You will likely need the NE (noescape) flag on the RewriteRule directive if you are receiving a %-encoded URL parameter value, otherwise the target URL will be doubly-encoded. The QUERY_STRING server variable is not decoded by Apache.
It also depends on how you are rewriting /search/query back to /?s=query (or presumably more like /index.php?s=query?) - presumably you are already doing this later in the config? You only want this redirect to apply to direct requests and not rewritten requests (otherwise you'll get a redirect loop). An easy way to ensure this is to check that the REDIRECT_STATUS env var is empty.
For example:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^s=(.*) [NC]
RewriteRule ^$ /search/%1 [NE,QSD,R,L]
Other points:
The QSD flag would be preferable (on Apache 2.4) to appending ? to the end of the susbtitution string in order to remove the query string.
The regex ^s=(.*) (the trailing $ was superfluous) does assume that s is the only URL parameter at the start of the query string. As it stands, everything is assumed to be part of this value. eg. s=foo&bar=1 will result in /search/foo&bar=1.
The NC flag on the RewriteRule directive is superfluous.
Should you also be checking for /index.php?s=<query>? (Or whatever file/DirectoryIndex is handling the request.)

htaccess send 404 if query string contains keyword

I'm seeing a lot of traffic which I suspect is probing for a flaw or exploit with the request format of
https://example.com/?testword
I figured while I look into this more I could save resources and disrupt or discourage these requests with a 404 or 500 response
I have tried
RewriteEngine On
RewriteCond %{QUERY_STRING} !(^|&)testword($|&) [NC]
RewriteRule https://example.com/ [L,R=404]
And some other variations on the Query string match but none seem to return 404 when testing. Other questions I have found look for query string values/pairs and rewrite them but no examples seem to exits for just a single value.
RewriteCond %{QUERY_STRING} !(^|&)testword($|&) [NC]
RewriteRule https://example.com/ [L,R=404]
There are a few issues here:
The CondPattern in your condition is negated (! prefix), so it's only successfull when the testword is not present in the query string.
The RewriteRule directive is missing the pattern (first) argument (or substitution (second) argument depending on how you look at it). The RewriteRule directive matches against the URL-path only.
When you specify a non-3xx status code for the R flag, the substitution is ignored. You should specify a single hyphen (-) to indicate no substitution.
To test that the whole-word "testword" exists anywhere in the query string, you can use the regex \btestword\b - where \b are word boundaries. Or maybe you simply want the regex testword - to match "testword" literally anywhere, including when it appears as part of another word? In comparison, the regex (^|&)testword($|&) would miss instances where "testword" appears as a URL parameter name.
Try the following instead:
RewriteCond %{QUERY_STRING} \btestword\b [NC]
RewriteRule ^$ - [R=404]
This matches the homepage only (ie. empty URL-path). The L flag is not required when specifying a non-3xx return status, it is implied.
The - (second argument) indicates no substitution. As mentioned above, when specifying a non-3xx HTTP status, the substitution string is ignored anyway.
To test any URL-path then simply remove the $ (end-of-string anchor) on the RewriteRule pattern. For example:
RewriteCond %{QUERY_STRING} \btestword\b [NC]
RewriteRule ^ - [R=404]
If your homepage doesn't accept any query string parameters then you could simply reject the request (ie. 404 Not Found) when a query string is present. For example:
RewriteCond %{QUERY_STRING} .
RewriteRule ^$ - [R=404]

Rewriting subdirectory to query string parameter

I have two requirements;
That, for example, /product/12345 is internally redirected to /product/product.php?product=12345.
That if the user tries to access /product/product.php in the URL bar, it is redirected to /product/ for tidiness.
Separate, they both work correctly, but together it results in an infinite loop - I know that I'm redirecting from /product/ to /product.php and back again, but the difference is internal vs external and I'm not sure how to distinguish between them.
RewriteEngine On
RewriteRule ^product/product.php /product/ [NC,R=307,END]
RewriteCond %{REQUEST_URI} !^/product/product.php [NC]
RewriteRule ^product/(.*) /product/product.php?product=$1 [NC]
There probably exist other solutions, but it works if you change two things:
Add a condition to the first RewriteRule that checks if the query string is empty, i.e. product/product.php without query string redirects to /product/.
Change (.*) in the second RewriteRule to (.+) or ([0-9]+) to only rewrite requests containing a product id (requests to /product/ are not rewritten).
RewriteEngine On
RewriteCond %{QUERY_STRING} ="" [NC]
RewriteRule ^product/product\.php$ /product/ [NC,R=307,END]
RewriteCond %{REQUEST_URI} !^/product/product\.php [NC]
RewriteRule ^product/(.+) /product/product.php?product=$1 [NC]
access /product/product.php in the URL bar, it is redirected to /product/ for tidiness
You might as well also redirect /product/product.php?product=12345 to the corresponding canonical URL (ie. /product/12345) - which you can do all in the same rule. If the product ID is numeric only then you should restrict your regex accordingly - this will also avoid the need for an additional condition.
For example:
# Canonical redirect
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{QUERY_STRING} ^(?:product=(\d*))?$ [NC]
RewriteRule ^product/product\.php$ /product/%1 [NC,R=307,L]
# Rewrite requests from "pretty" URL to underlying filesystem path
RewriteRule ^product/(\d*) /product/product.php?product=$1 [L]
The condition that checks against the REDIRECT_STATUS environment variable is necessary to prevent a redirect loop in this instance since the query string is entirely optional.
By restricting the match to digits-only, we avoid the need for an additional condition on the internal rewrite, product.php won't match. If the product id can contain letters then restrict the pattern to avoid dots (.), eg. ([^./]*).
Only include a NC flag on the internal rewrite if this is strictly necessary, otherwise this potentially creates a duplicate content issue.

No trailing slash causes 404, how to fix using htaccess?

The URLs are:
(Doesn't work) http://example.com/seller/samsung
(Works) http://example.com/seller/samsung/
The .htaccess rule I have for these types of URLs looks like:
RewriteRule ^seller/[^/]+/(.*)$ ./$1
What can I do to make both of these URLs to go to the same page?
You could just force a trailing slash to appear on the end of your URLs. You can do that by using the following in your .htaccess:
RewriteCond %{REQUEST_URI} !(/$|\.)
RewriteRule (.*) %{REQUEST_URI}/ [R=301,L]
Just make sure you clear your cache before you test this.
EDIT:
RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]
What does the above do? So the condition grabs your directory, so for example /samsung and will check if it has a / on the end. If it does not, it will grab the directory at the end of URL (once again /samsung and add a / on to it. It will do this using a 301 redirect and would leave you with /samsung/.
As for the L flag (taken from official documentation):
The [L] flag causes mod_rewrite to stop processing the rule set. In
most contexts, this means that if the rule matches, no further rules
will be processed. This corresponds to the last command in Perl, or
the break command in C. Use this flag to indicate that the current
rule should be applied immediately without considering further rules.