Apache redirect for adding missing .html at the end - apache

I want to redirect any request that doesn't have the last segment contain a dot to .html
examples:
/travels/
/travels.html
/travels/categories/new-zealand
/travels/categories/main.js
Line 2 and 4 should not be redirected while line 1 and 3 should be redirected to:
/travels.html
/travels/categories/new-zealand.html
I already have this regex that seems to work for capturing: ^(https?:\/\/.+(\..+)*\/)?[^\s.]+$
How do I exactly make this redirect happen? I have a vserver with an apache werbserver that is running and mod_rewrite is enabled. How exactly would the rewrite statement look and where do I put it? If I put it in a .htaccess file, where do I keep that? Inside the root of the page or anywhere?

You can not match against host and https header in the rule's pattern. You can only match against URL path in a RewriteRule . To check the host and https header you need to use RewriteConds
RewriteEngine on
# URL scheme is HTTPS
RewriteCond %{HTTPS} on
# Host is www.example.com or example.com
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
#URL path is /travels/ then redirect the request to /travels.html
RewriteRule ^/?travels/$ /travels.html [R,L]
This will redirect https://example.com/travels/
to https://example.com/travels.html . This changes the URL in your browser from old to the new one, if you want the redirection to happen internally then just remove the R flag.

Related

.htaccess redirect not redirecting

I am trying to Redirect pages to new location on the same website using .htaccess
the physical file name is displayitems.php but there is a rule in .htaccess
RewriteRule ^buy-online-(.*) ./displayitems.php?url=$1
which is to handle the user friends URLs and works well.
Now i want to redirects these user friendly urls to new location which is on the same website for eg.
redirect https://example.com/buy-online-alhabib-rings4-sku-1658906163 https://example.com/products/jewelry/buy-online-alhabib-rings4-sku-1658906163 [R=301]
redirect https://example.com/buy-online-alhabib-rings3-sku-1658906162 https://example.com/products/jewelry/buy-online-alhabib-rings3-sku-1658906162 [R=301]
redirect https://example.com/buy-online-alhabib-rings2-sku-1658906161 https://example.com/products/jewelry/buy-online-alhabib-rings2-sku-1658906161 [R=301]
redirect https://example.com/buy-online-alhabib-rings1-sku-1658906160 https://example.com/products/jewelry/buy-online-alhabib-rings1-sku-1658906160 [R=301]
these user friendly url doesn't have any extensions like ".php" ".htm" etc
but nothing happening.
I have added this code in php file to check if url doesn't contain \products\ than redirect it to new location with the same name, for testing i just redirect it with 302 once all tested i will change it to 301
if (strpos($_SERVER['REQUEST_URI'], "/products/") === false) { $NewAddress = strtolower("Location:". $ini['website_address_https'] . "products/".$Product['categoriesname']."/".$Product['BrandName'].$_SERVER['REQUEST_URI']); header("$NewAddress",TRUE,302); }
redirect https://example.com/buy-online-alhabib-rings4-sku-1658906163 https://example.com/products/jewelry/buy-online-alhabib-rings4-sku-1658906163 [R=301]
There are 3 main issues here:
The mod_alias Redirect directive takes a root-relative URL-path (starting with a slash) as the source URL, not an absolute URL. So the above will never match.
You have mixed syntax with mod_rewrite. [R=301] is a RewriteRule (mod_rewrite) flags argument and has nothing to do with the mod_alias Redirect directive. Redirect takes the HTTP status code as an optional second argument. eg. Redirect 301 /buy-online-alhabib-rings4-sku-1658906163 ...
Since you are using mod_rewrite (ie. RewriteRule) for your internal rewrite, you should use mod_rewrite for external redirects as well to avoid potential conflicts. These redirects then need to go before your internal rewrite.
Additionally,
In the 4 redirects you have posted it looks like you are simply injecting /products/jewelry at the start of the URL-path. This does not need 4 separate rules, providing you are wanting to redirect all URLs that following this particular format.
Try the following instead:
RewriteEngine On
# Inject (redirect) "/product/jewelry" at the start of the URL-path
RewriteRule ^buy-online-alhabib-rings\d-sku-\d+$ /products/jewelry/$0 [R=301,L]
# Internal rewrite
RewriteRule ^buy-online-(.*) displayitems.php?url=$1 [L]
The $0 backreference in the first rule contains the entire URL-path that is matched by the RewriteRule pattern.
Note that I also removed ./ from the start of the substitution string in the last rule. This is unnecessary here.

.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>.

redirect exact url to another url

There are a bazillion examples online of doing redirects via apache's htaccess, but I can't find any example of redirecting a full URL match to another full URL.
For instance, I have an existing website at
https://example.com
How do I redirect some specific URLs for that domain to a different one:
https://example.com/login --> https://my.example.com/login
https://example.com/register --> https://my.example.com/register
For every other every other path on example.com I need to remain untouched so my site still works fine (i.e. /blog shouldn't redirect somewhere else).
You can use the following :
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteRule ^(login|register)/?$ http://my.example.com/$1 [L,R]
This will redirect example.com/login or example.com/register to http://my.example.com/
You can alternatively accomplish this using the RedirectMatch directive (if the newurl is on a diffrent webserver) :
RedirectMatch ^/(login|register)/?$ http://my.example.com/$1

Apache mod_rewrite - want a file system redirect not a 301 redirect

I have example1.com on a shared web host running Apache. It has a directory example1.com/foo. I now want example2.com to serve the same content from example1.com/foo, except at the example2.com root without the intervening directory in the URL. Like example2.com/bar.html should serve the same content as example1.com/foo/bar.html .
RewriteEngine on
RewriteCond %{HTTP_HOST} example2.com$ [NC]
RewriteRule ^(.*)$ foo/$1 [NC]
This simple rewrite rule takes any request intended for example2.com and inserts the foo/ to point to the content which is in that directory. Problem is this keeps doing an external 301 redirect. I don't want that, I want the browser to stay on example2.com without redirecting while Apache serves up the content from /foo in the filesystem.
Been over the Apache mod_rewrite docs several times, which say how to force a 301 redirect with the [R] flag but don't say how to force it NOT to happen. What am I missing here? It is behaving the same on both my Linux shared host and a local test with Apache on Windows.
Thanks!
I figured this out. The 301 was happening because I had the directory name wrong in the rule. So the result of the rule pointed to a path that didn't exist, which makes Apache try to fallback from the file system redirect to a 301 redirect.
Then I had to fix an infinite loop, since that above rule always adds "foo" to the URL even if it's already present so I'd get foo/foo/foo/foo/... . We need to add it only if it's not already there. Had to do it with this two-step rule, because you can't use wildcards in a capturing group of a negative rule. But this seems to work, adding "foo" when the host is example2.com and the URL does not already contain "foo".
RewriteEngine on
RewriteCond %{HTTP_HOST} example2.com$ [NC]
RewriteRule !^foo - [C]
RewriteRule ^(.*)$ foo/$1 [NC,PT]

htaccess redirect domain and mask url

I want to redirect a domain name : http://www.newdomain.com to http://sub.maindomain.com
I have edited .htaccess as:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !sub.maindomain.com$ [NC]
RewriteRule ^(.*)$ http://sub.maindomain.com/$1 [L,R=301]
It redirects but the http://sub.maindomain.com visible in the address bar . Help! How to do the masking so that http://www.newdomain.com would be visible . Thanks
And also I want create a subsite http://sub.newdomain.com . How to do it with .htaccess .
If www.newdomain.com and sub.maindomain.com are on different hosts, the only way to get the content on sub.maindomain.com to be served while the browser's URL address bar says www.newdomain.com is to fetch the content from sub.maindomain.com on behalf of the browser. Since as far as the browser is concerned, it's looking at content on newdomain.
You can do this either by setting up a proxy using apache or maybe a script. Using apache, you'd need access to your vhost config for the www.newdomain.com domain. You can set it up like:
ProxyPassMatch ^(.*)$ http://sub.maindomain.com$1
Take a look at the mod_proxy docs for more info on the flags you can pass this directive, to tweak timeouts and retries.
If you want to setup a php script to proxy, you'll need to route all requests to this php script, so in your htaccess file in your www.newdomain.com document root, add (assuming this php script is called proxy.php):
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/proxy.php
RewriteRule ^(.*)$ /proxy.php?url=$1 [L,QSA]
Then in proxy.php, look for the url query string, load that page, and output it to the browser.
Though all of this is much easier if you can just point both domains to the same host.