htaccess redirect to exclude certain pages - apache

My htaccess file currently redirects everything and has this
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.domain.co.uk/$1 [R,L]
I need to exclude two urls that begin with "send"
I changed the last line to
RewriteRule !^send(.*) https://www.domain.co.uk/$1 [R,L]
It excluded the send urls but any url in a subfolder is redirected to the root index page.

RewriteRule !^send(.*) https://www.domain.co.uk/$1 [R,L]
Negated patterns don't capture anything (by definition), but trying to capture everything after send when send is not present in the URL, doesn't make much sense.
You can do something like the following and use the REQUEST_URI server variable in the substitution instead of the backreference:
RewriteRule !^send https://www.domain.co.uk%{REQUEST_URI} [R,L]
Note that the REQUEST_URI server variable already contains the slash prefix.

Related

.htaccess 301 redirect whole URL including Domain

I need to redirect around 300 URLs on a multidomain site that has the same URL structure on the different domains. For example:
https://www.example.com/de/products.html needs to be redirected to https://www.example.org/de/products.html
So my usual approach does not work:
RedirectMatch 301 /de/products.html$ /de/products.html
I would need something like
RedirectMatch 301 https://www.example.com/de/products.html$ https://www.example.org/de/products.html
which obviously doesn't work or I just didn't get to work.
Not sure if important, but it's a TYPO3 instance.
The mod_alias RedirectMatch directive matches against the URL-path only. To match the hostname you'll need to use mod_rewrite with an additional condition (RewriteCond directive) that checks against the HTTP_HOST server variable (the value of the Host HTTP request header).
Also, since the URL structure is the same on both domains then you only need a single rule - just use the same URL-path from the initial request. No need to do one-by-one redirects as you seem to be trying to do.
For example, the following would need to go at the top of the .htaccess file before any existing rewrites:
RewriteEngine On
# Redirect everything from example.com to example.org and preserve the URL-path
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^ https://www.example.org%{REQUEST_URI} [R=301,L]
This checks for both example.com and www.example.com.
The REQUEST_URI server variable already contains a slash prefix, hence it is omitted in the substitution string.
Test first with a 302 (temporary) redirect to avoid potential caching issues.
UPDATE:
But I don't want to redirect all URLs, just some.
To redirect a specific URL to the same URL at the target domain, as per your original example:
# Redirect "/de/product.html" only
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^de/products\.html$ https://www.example.org/$0 [R=301,L]
The above redirects https://www.example.com/de/products.html only to https://www.example.org/de/products.html.
The $0 backreference contains the entire URL-path that the RewriteRule pattern matches against.
How to extend your snippet with /de/ or /fr/ etc.? For example I want to redirect example.com/de/products.html but not example.com/products.html
Maybe the above example is what you require. Alternatively, to redirect /de/<something> (or /fr/<something>) only and not just /<something>, you could do something like this:
# Redirect "/<lang>/<something>" only, where <lang> is "de" or "fr"
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^(de|fr)/[^/]+$ https://www.example.org/$0 [R=301,L]
The above will redirect https://example.com/de/<something> to https://www.example.org/de/<something>.

htaccess rewrite rule from folder to folder with querystring

I am looking to include a rewrite rule for the following but can't seem to get it to work. I don't want to pass any query string in but I need to add one to the rule.
I want this URL:
https://example.co.uk/vehicles/
to point to:
https://example.co.uk/search-results/?category=1
but keep the first URL in the address bar.
I need to pass in a variable called category with a value.
I tried the following but it didn't work for me:
rewriterule ^vehicles/$ search-results/?category=1 [NC, L]
Any help would be appreciated.
RewriteEngine On
RewriteRule .* ? [F,L]
RewriteRule ^(.*)$ https://example.co.uk/$1 [R,L]
RewriteRule ^ad/(.*/)?([0-9]+)$ view-ad/?ad=$2 [NC,L]
RewriteRule ^vehicles/$ search-results/?category=1 [NC,L]
I managed to solve it. It was due to an Ajax load on the page.
Glad you solved your initial query, however, the following two directives in your posted .htaccess file will break your site, so presumably, these have already been removed?
RewriteRule .* ? [F,L]
RewriteRule ^(.*)$ https://example.co.uk/$1 [R,L]
The first directive simply blocks all access to your site, returning a 403 Forbidden response. And the second directive will result in a redirect loop.
Now that it works is it possible to have another rewrite rule that does this https://example.co.uk/vehicles/?something=1 and rewrite to https://example.co.uk/vehicles/?category=1&appendsomething=1 but only display https://example.co.uk/vehicles/
I assume you mean https://example.co.uk/search-results/?category=1&something=1 (as opposed to /vehicles/) - where something=1 is appended on the end of the query string?
You wouldn't be able to make this "display as https://example.co.uk/vehicles/" - as this would conflict with your existing (working) directive.
However, you could potentially modify your existing directive to handle requests for /?something=1 and pass this through to the substitution. This would simply require the addition of the QSA flag (Query String Append). For example:
RewriteRule ^vehicles/$ search-results/?category=1 [QSA,NC,L]
The QSA flag results in the query string from the request being appended to the end of the query string specified in the RewriteRule substitution.
UPDATE: To redirect HTTP to HTTPS, you would need something like the following instead:
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://example.co.uk/$1 [R,L]
Note the preceding RewriteCond directive - this ensures that only HTTP requests are redirected, not everything (HTTP and HTTPS), so avoiding a redirect loop. Ultimately this should also be a 301 (permanent) redirect, so you should change R to R=301, but only when you are sure it's working OK.

htaccess - Simple rewrite rule not triggering

I'm trying to match a simple rule to rewrite a url but it's just not matching. I want to redirect
https://example.com/web/thanks/
to
https://example.com/thanks.php
Here's what I've tried
RewriteEngine On
RewriteBase /
RewriteRule ^thanks/$ https://example.com/thanks.php [R=302,L]
RewriteEngine On
RewriteRule ^thanks/$ https://example.com/thanks.php [R=302,L]
RewriteEngine On
RewriteBase /
RewriteRule ^/(.*)/thanks/$ https://example.com/thanks.php [R=302,L]
RewriteEngine On
RewriteBase /
RewriteRule ^web/thanks/$ https://example.com/thanks.php [R=302,L]
and many more tiny variations but none of them are triggering. I tried using this online tool and it returns "This rule was not met". What am I doing wrong?
To rewrite, just use your last rule
RewriteRule ^web/thanks/?$ /thanks.php [L]
with the following changes
no RewriteBase, this is only relevant for some relative URLs
optional trailing slash /?, if you want both /web/thanks or /web/thanks/ to work
no domain name, because this might trigger a redirect instead of a rewrite, see RewriteRule
Absolute URL
If an absolute URL is specified, mod_rewrite checks to see whether the hostname matches the current host. If it does, the scheme and hostname are stripped out and the resulting path is treated as a URL-path. Otherwise, an external redirect is performed for the given URL. To force an external redirect back to the current host, see the [R] flag below.
no R|redirect flag, because this triggers a redirect instead of a rewrite
The pattern ^.*thanks/$ or ^(.*)thanks/$ also works, but it matches any URL ending in thanks/, like /hellothanks/, /areyousurethanks/, /some/path/thanks/, ...

Using a .htaccess to RewriteRule and Redirect 301 at the same time?

I have a couple of specific URLs that I want to display differently on my website. For example I want "/contact.php" to become "/contact". So I added this to my .htaccess:
RewriteRule ^contact$ contact.php
And to avoid having 2 different URLS pointing to the same page, I also want to do a 301 redirect between the old URL and the new one:
Redirect 301 /contact.php http://www.example.com/contact
Each of the line above works well separately. But if I add them both in my htaccess, I have a redirect loop. How can I fix that?
In the end, if I either type "/contact" or "/contact.php", I want to see the contact page with the url "/contact".
Edit: I also tried things like that, and it doesn't work:
RewriteRule ^/contact\.php$ http://www.example.com/contact [R=301,L]
RewriteRule ^/contact$ /contact.php [L]
Yes it will indeed cause redirection loop since mod_rewrite rules are applied in a loop. Here value of REQUEST_URI changes to contact.php after first rule and to contact by your second rule.
To avoid this looping you need to use %{THE_REQUEST} in your external redirect rule as THE_REQUEST variable represents original request received by Apache from your browser and it doesn't get overwritten after execution of some other rewrite rules. Example value of this variable is GET /index.php?id=123 HTTP/1.1.
Use this:
RewriteEngine On
# external redirect from /contact.php to /contact
RewriteCond %{THE_REQUEST} \s/+(contact)\.php\[\s?] [NC]
RewriteRule ^ /%1? [R=302,L]
# internal forward from /contact to /contact.php
RewriteRule ^(contact)/?$ $1.php [L,NC]
Change 302 to 301 once you make sure it is working fine for you.

CakePHP 301 Redirects appending extra query string parameter

I am trying to redirect old asp pages on a domain name so they link to their respective pages on the CakePHP version (using 1.3). The domain name is the same. These redirects are being added so results in search engines go to the new Cake page.
I have a bunch of Redirect 301's in my /.htaccess file (app/.htaccess and app/webroot/.htaccess are default).
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule ^$ app/webroot/ [L]
RewriteRule (.*) app/webroot/$1 [L]
Redirect 301 /contacts.asp http://domain/contacts
Redirect 301 /users.asp http://domain/users
</IfModule>
But for some reason, when I go to any of the urls to test the redirects, it appends an extra query string parameter. For example:
Going to: http://domain/contacts.asp results in http://domain/contacts?url=contacts.asp
So the redirect is working but it is appending the url query string parameter. I don't want to completely remove all query string parameters because some of the old asp links have query string parameters that I would also like passed to the corresponding Cake page.
I believe the "url" query string parameter is coming from the app/webroot/.htaccess file as seen:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
Note that when I put all my 301 redirects into my Virtual hosts file, the url parameter is not appended. I would like to keep all these redirects in my .htaccess file. How can I prevent this url query string parameter from being appended?
This looks like a case of mod_rewrite and mod_alias stepping over each other. The URI processing pipeline doesn't end when a Redirect directive is applied, it continues through the pipeline and mod_rewrite does its thing. Unfortunately, the end result isn't always what you want. You could just stick with mod_rewrite and drop the Redirect directives.
You can remove the 2 Redirect directives and add these 2 RewriteRules above the ones that map requests to the app/webroot:
RewriteRule ^contacts\.asp$ http://domain/contacts [L,R=301]
RewriteRule ^users\.asp$ http://domain/users [L,R=301]