redirect any link on any subdomain-url to another domain - apache

I registered a expired domain to forward all incoming links to another domain. The problem is: many inlinks are placed on subdomains, for example: axa-art.cdn.contento-v41.eu/axa-art/0eee9cec-58cb-45b2-a4e2-b5f73920068e_091216_axa+art_classic+car+study_de_rz.pdf
I am looking for a 301 redirect rule in htaccess that forward any url (no matter on main domain or subdomain) to "new-url.tld"
axa-art.cdn.contento-v41.eu
axa-art.cdn.contento-v41.eu/slug
any-subdomain.contento-v41.eu
any-subdomain.contento-v41.eu/slug
all of this example above should
forward to this exact URL: new-domain.tld
Question 1:
Is it possible to create a "general" rule and place it into htaccess of the main directory?
Question 2:
Or do i have to write a specific rule for each subdomain?
Question 3:
Do I have to create a sub-directory and create a separate htaccess in every sub-directory for each subdomain I want to add redirection-rules?
Help or suggestions are highly appreciated. Thank you very much for your help in advance.

This isn't just a .htaccess question. In order for your server to receive requests to <any-subdomain>.example.com the necessary DNS and server config directives need to be in place. If the request doesn't reach your server then you can't implement a redirect in .htaccess.
So, I suspect that these subdomains are not even resolving?
You either need to create the necessary DNS A records and ServerAlias directives one by one for each hostname (ie. subdomain) or create a "wildcard" DNS A record (and ServerAlias *.example.com directive in the vHost). But then you still have an issue with these hostnames being covered by an SSL cert if you need to redirect from HTTPS.
You can then create the necessary redirect in .htaccess. Although, since you need access to the server config (or a using a control panel that does this for you) to implement the directives above, you should also implement this redirect in the server config also.
For example, at the top of your .htaccess file, before the existing directives (or in your vHost):
RewriteEngine On
RewriteCond %{HTTP_HOST} !^new\.example$
RewriteRule ^ https://new.example%{REQUEST_URI} [R=301,L]
The above states... for any request that is not for new.example then 301 redirect to https://new.example/<same-url>.
However, if you have access to the server config and this other domain is configured in its own vHost container then the redirect can be simplified:
Redirect 301 / https://new.example/
UPDATE#1:
this rule does forward any URL form the main domain to the new domain.
# Permanent URL redirect- by netgrade
RewriteEngine on
RewriteCond %{REQUEST_URI} !https://www.marco-mahling.de/$
RewriteRule $ https://www.marco-mahling.de/ [R=302,L]
The rule I posted above should probably replace your existing rule entirely.
Yes, your rule does redirect every URL to the root of the new domain, but it is arguably incorrect. The RewriteCond directive is superflous and isn't actually doing anything. The REQUEST_URI server variable contains the URL-path, it never contains the scheme + hostname. So, the RewriteCond directive you've posted will always be successful.
If that is the rule you currently have then it would already redirect everything. In which case your problem would seem to the necessary DNS and server config directives as mentioned above.
From your directives, I assume that the other domain actually points to a different server (or different vHost on the same server). Otherwise, this would have resulted in a redirect-loop. In which case, you only need the much simpler Redirect directive that I posted above.
UPDATE#2: That works fine BUT the incoming links are still not forwarded cuz of a "%" in the url: https://axa-art.cdn.contento-v41.eu/axa-art%2F0eee9cec-58cb-45b2-a4e2-b5f73920068e_091216_axa+art_classic+car+study_de_rz.pdf
It's actually because of the %2F - an encoded slash (/) in the URL-path. By default, Apache will reject such URLs with a 404 (for security reasons).
To allow encoded slashes in the URL you would need to set AllowEncodedSlashes On in the server config (or vHost container). You cannot set this in .htaccess. (The server generated 404 occurs before .htaccess is even processed.)
However, I would express caution about enabling this feature. (Is there a specific requirement here? Are you recreating these documents on the new server?)
If this request was intended to map directly to a PDF file on disk then this actually looks like an incorrectly URL encoded request, since a slash / is not a permitted filename character on either Windows or Linux.
If you enable AllowEncodedSlashes then the above RewriteRule will redirect the request to /axa-art/0eee9cec....pdf - note the %-decoded / in the resulting URL. You would need to take additional steps to maintain the URL-encoding (if that was required), but as I say, that looks like a mistake to begin with.

Related

Rewrite URL in XAMPP VirtualHost

Been trying to play with mod_rewrite through .htaccess in one Xampp virtualhost, but I am not getting the results that I am looking for.
What I am tring to do is to rewrite the following: www.example.com/name/billy.html to: www.example.com/billy
Without trying to rewrite the URLs the virtualhost is working fine, I have access to all pages. However, when I add the .htaccess with the corresponding rewrite rule I get a 404 page not found. The regex is working as expected though. I see that the request to www.example.com/name/billy.html it's been rewritten to www.example.com/billy, but the page doesn't load.
The name folder exists in the file structure and the .htaccess is inside the example folder.
Currently, my vh configuration looks like this:
<VirtualHost *:80>
DocumentRoot "/Applications/XAMPP/xamppfiles/htdocs/example"
ServerName www.example.com
<Directory "/Applications/XAMPP/xamppfiles/htdocs/example">
Options Indexes FollowSymLinks ExecCGI Includes
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
And this is the content of the .htaccess file:
RewriteEngine On
RewriteRule ^name\/([a-z]+).html$ /$1 [L,NC,R]
What is missing?
What I am tring to do is to rewrite the following: www.example.com/name/billy.html to: www.example.com/billy
You seem to have the process the wrong way round and possibly mixing up "rewrites" and "redirects"?
You should be internally rewriting from the visible "friendly" URL to the underlying file-path that actually handles the request. You are trying to do the opposite here. How is your system expected to handle a request for /billy? (It doesn't, and generates a 404.)
You may be thinking you can change the URL using .htaccess (mod_rewrite) alone? But no, that is not how this works.
RewriteRule ^name\/([a-z]+).html$ /$1 [L,NC,R]
You mention "rewrite", but this directive is in fact a "redirect" (as indicated by the R flag). Specifically, a 302 (temporary) redirect in this instance.
(You might actually want to implement a redirect like this, if you are changing an existing URL structure, but more on that later*1)
A URL "rewrite" is entirely internal to the server. The user only sees the public URL, they do not see the URL that it might be rewritten to. You (the user) can't "see" a rewrite.
A "redirect" on the other hand, usually refers to an external redirect, ie. a 3xx response sent back to the client with an instruction to make a new request to a different URL. The URL being redirected to is visible to the user. This is used when content has moved to a different URL.
So, following your example, you should be requesting/linking to (in your HTML source) the short/friendly URL /billy and internally rewriting the request to /name/billy.html that actually handles the request.
For example:
RewriteEngine On
# Rewrite from "billy" to "name/billy.html"
RewriteRule ^[a-z]+$ name/$0.html [NC,L]
The $0 backreference contains the entire URL-path that is matched by the RewriteRule pattern.
Only use the NC flag if you do need to match uppercase letters as well. But a request for /Billy won't serve /name/billy.html on a case-sensitive OS.
And that's really it, with regards to the URL-rewritting, you can stop reading here.
*1 Redirect from old to new
Regarding the external "redirect" mentioned above. You might choose to implement a redirect (in the opposite direction) if you are changing an existing URL structure and the old URLs have been indexed by search engines and/or linked (or bookmarked) to by external third parties - in order to preserve SEO and keep users happy.
For example, say your original URLs were of the form /name/billy.html and you later decided to change your URLs to /billy instead. You first change the URLs in the HTML source and implement the "rewrite" as mentioned above so the new URLs now work. You then might implement an external redirect from the old /name/billy.html URL to the new /billy URL.
For this, you would use a directive like you had initially, except you have to be careful of redirect-loops because you are already rewriting the request in the opposite directive. You only want to redirect "direct/initial" requests and not rewritten requests by the earlier rewrite (that is actually later in the file). An easy way to check for "direct" requests is to check against the REDIRECT_STATUS environment variable, which is empty on the initial request and set to 200 (as in 200 OK status) when the request is rewritten.
For example, the following "redirect" would go before the above "rewrite", immediately after the RewriteEngine directive:
# Redirect from "name/billy.html" to "/billy"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^name/([a-z]+)\.html$ /$1 [R=301,NC,L]
This should ultimately be a 301 (permanent) redirect since the URL has presumably changed permanently. However, always test with 302 (temporary) redirects to avoid potential caching issues.
Further reading:
Reference: mod_rewrite, URL rewriting and "pretty links" explained

Htaccess redirect URL to another one and delete characters

I want an old website to be redirect to the new one, the URL looks like this : https://test.fr/directory/homepage.html
In my .htaccess file I have :
RedirectPermanent / https://google.com/`
But what it does : https://google.com/directory/homepage.html
I'd like to redirect to https://google.com/ and delete everything after the .com/ but I have no idea how.
Just use the rewriting module:
RewriteEngine on
Rewrite ^ https://google.com/ [R=301,END]
Obviously the rewriting module needs to be loaded into the http server for that. This usually is the case, certainly for all hosting providers.
If you only want to redirect that specific URL inside your http host, then that should do:
RewriteEngine on
Rewrite ^/?directory/homepage\.html$ https://google.com/ [R=301,END]
You can implement such directives in a distributed configuration file (".htaccess"). You should prefer the actual http server's host configuration though, if you have access to that.

Htaccess rewrite subfolder to subdomain

i have a domain with many subdomain; what i want to do is to map specific subdomains do specific subfolder.
let's suppose the domain is example.com, i have these domains:
example.com
www.example.com
demo1.example.com
demo2.example.com
and 2 subfolders in my var/www/html folder:
/var/www/html (for example.com and www.example.com)
/var/www/html/demo1 (for demo1.example.com)
/var/www/html/demo2 (for demo2.example.com)
So what i want to is set up the correct mapping so that:
opening (www.)example.com/demo1 should redirect to demo1.example.com
opening (www.)example.com/demo2 should redirect to demo2.example.com
opening (www.)example.com/anything-else should do nothing (content in /var/www/html)
Obviusly demo1.example.com should use the content in /var/www/html/demo1 and demo2.example.com should use the content in /var/www/html/demo2
You probably want to implement rules handling both directions:
1. redireting requests to the "www" host to the "subdomain" (actually another host name)
2. rewriting requests to the non-www hosts to a folder, if such folder exists
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$
RewriteRule ^/?demo1/(.*)$ https://demo1.example.com/$1 [R=301]
RewriteRule ^/?demo2/(.*)$ https://demo2.example.com/$1 [R=301]
RewriteCond %{HTTP_HOST} ^demo1\.example\.com$
RewriteRule ^ /demo1/%{REQUEST_URI} [END,QSA]
RewriteCond %{HTTP_HOST} ^demo2\.example\.com$
RewriteRule ^ /demo2/%{REQUEST_URI} [END,QSA]
You could certainly implement a more generalized rule for the second part (the internal rewriting), but above explicit approach is easier to reach, thus easier to maintain. I prefer it for that reason.
It is a good idea to start out with a 302 temporary redirection and only change that to a 301 permanent redirection later, once you are certain everything is correctly set up. That prevents caching issues while trying things out...
In case you receive an internal server error (http status 500) using the rule above then chances are that you operate a very old version of the apache http server. You will see a definite hint to an unsupported [END] flag in your http servers error log file in that case. You can either try to upgrade or use the older [L] flag, it probably will work the same in this situation, though that depends a bit on your setup.
These rules will work likewise in the http servers host configuration or inside a dynamic configuration file (".htaccess" file). Obviously the rewriting module needs to be loaded inside the http server and enabled in the http host. In case you use a dynamic configuration file you need to take care that it's interpretation is enabled at all in the host configuration and that it is located in the host's DOCUMENT_ROOT folder.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

.htaccess 301 redirect old to new domain, from hosting root to subfolder, working but why?

The scenario: I've moved a WordPress website to a new domain and want to 301 redirect all the pages from the old domain to the new domain. Both sites are on the same hosting account running Apache. The old site is at the root level (public_html), and the new site is in a subfolder (below/inside the root).
I've managed to make this work, but I'd like to learn and understand why it works. So below is a quick overview of my 'journey' and solution, together with three specific questions.
First I tried to do the redirects like this (code added to the root .htaccess file):
# 301 Page Redirects - not working - causes redirect loop
redirect 301 / https://new-domain.com/
redirect 301 /services/ https://new-domain.com/services/
redirect 301 /recipes/ https://new-domain.com/recipes/
But this causes a redirect loop. I'm guessing because the .htaccess file with these rules is at the root level and therefore also affects the subfolders.
Question 1: Is my assumption above about the reason for the redirect loop correct?
Then I tried to be more specific and put this code in the root .htaccess file instead:
# 301 Page Redirects - not working - does nothing at all - not sure why
redirect 301 https://old-domain.com/ https://new-domain.com/
redirect 301 https://old-domain.com/services/ https://new-domain.com/services/
redirect 301 https://old-domain.com/recipes/ https://new-domain.com/recipes/
I was hoping the above code would do the trick, because it's more specific about the old domain. My thinking was that it specifies the old domain exactly and so would circumvent the redirect loop. But instead this code seems to have no effect at all. The redirect loop was gone, but now no redirects were happening anymore at all.
Question 2: Why would the above code not produce any redirects at all?
Then I found this answer and applied the code from that, which works perfectly and creates all the redirects. Plus it's much more elegant than my previous attempts above. This is the code:
# 301 Redirects from old-domain.com to new-domain.com - THIS CODE WORKS - Yay!
RewriteEngine On
RewriteCond %{HTTP_HOST} ^old-domain.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.old-domain.com$
RewriteRule (.*)$ https://new-domain.com/$1 [R=301,L]
Question 3: Why does this code not cause any redirect loops when I place it in the root .htaccess?
I realise I'm copy/pasting code without fully understanding why it works. So I'd love an explanation in simple terms about these behaviours. Thank you.
Answer 1:
From the info that you have provided, I would say no. You did not specify if the new-domain.com website is configured (in apache configuration) with its document root being public_root or public_root/subfolder (judging by the described behaviour I would say it is the former). In that case, when you request https://old-domain.com/anything, the server will (because of the unconditional redirect in your first rule) respond with redirect to https://new-domain.com/anything. Client browser will then request that URL and it will hit the same Apache and same .htaccess, which will again result in the same redirect, causing the loop.
Answer 2:
Redirect syntax:
Redirect [status] [URL-path] URL
The old URL-path is a case-sensitive (%-decoded) path beginning with a
slash.
In your rule, you are specifying [URL-path] as https://old-domain.com/, which is wrong: it can be /, /services/, or /recipes, but not https://old-domain.com/ or https://old-domain.com/services/. The request [URL-path] does not match [URL-path] specified in your rule, so redirect never happens.
Answer 3:
This basically does the same thing as your first rule in Answer 1., with one important difference: the server will respond with redirect only if the hostname in request (or to be more precise, the content of the Host: header in request) is equal to old-domain.com or www.old-domain.com, which will prevent the loop since the second request from the client will use new-domain.com hostname.
Also, from the above, seems like your "new" website in subfolder will never be served: either if old-domain.com or new-domain.com is requested, the site from public_html folder will be shown (and only the hostname in clients browser address bar will change).

Redirect Without changing URL Apache

I want to redirect one URL to another without changing the Browser URL
www.example.com/abc/(.*).xml should redirect to www.example.com/abc/xyz/index.htm?file=$1
But the Browser should display www.example.com/abc/(.*).xml
You can use a RewriteRule:
RewriteEngine On
RewriteRule /abc/(.*)\.xml$ /abc/xyz/index.htm?file=$1 [L]
Make sure you have mod_rewrite enabled and put this either in your VirtualHost config, or in a .htaccess file in your DocumentRoot
As Constantine posted on the accepted solution, the [P] flag is dangerous as it converts the server as a proxy.
See [this]: https://serverfault.com/questions/214512/redirect-change-urls-or-redirect-http-to-https-in-apache-everything-you-ever?noredirect=1&lq=1
P = Proxy. Forces the rule to be handled by mod_proxy. Transparently provide content from other servers, because your web-server fetches it and re-serves it. This is a dangerous flag, as a poorly written one will turn your web-server into an open-proxy and That is Bad.