mod_alias vs mod_rewrite precedence - apache

I have an apache config file making use of both mod_alias's Redirect directive, and mod_rewrite's RewriteRule.
From my understanding, mod_alias works in order of top to bottom of the file, and mod_rewrite the opposite, the last rule is matched, unless you terminate with the [L] flag.
My question is, my Redirect rules are placed above the RewriteRule, yet the RewriteRule still seems to be being applied, so I end up redirecting everyone to the same url.
What I am trying to achieve is redirect certain locations to another webserver, and have a catch-all with mod-rewrite so a snippet looks like this
<VirtualHost *:80>
ServerName example.com
Redirect permanent "/foo/bar/location1/" "https://example2.com/foo/baz/location1"
Redirect permanent "/foo/bar/location2/abc" "https://example2.com/foo/baz/location2/def"
RewriteEngine on
RewriteRule ^.*$ "https://example2.com/catch-all/? [R=301, L]
Also, do these behave differently if they are inside a block or outside?

You have to write Redirect rule after Rewrite rule as it will first check what is the rewrite rule it has to follow and then the redirect rules.
<VirtualHost *:80>
ServerName example.com
RewriteEngine on
RewriteRule ^.*$ "https://example2.com/catch-all/? [R=301, L]
Redirect permanent "/foo/bar/location1/" "https://example2.com/foo/baz/location1"
Redirect permanent "/foo/bar/location2/abc" "https://example2.com/foo/baz/location2/def"

Related

I'm trying to redirect /example to example.html in Apache's httpd.conf, but it doesn't work

Here's the code I'm trying to apply in httpd.conf:
<VirtualHost *:80>
ServerName www.test.com
ServerAlias www.test.com
DocumentRoot /home/test_com
ErrorLog /home/logs/apache/www_test/www.test.com-error_log
CustomLog /home/logs/apache/www_test/www.test.com.-access_log common env=!do_not_log
# https redirect
RewriteEngine On
RewriteCond %{HTTP_HOST} www.test.com
RewriteCond %{REQUEST_URI} /example
RewriteRule . https://www.test.com/example.html [R=303,L]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}
<Directory "/home/test_com/">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
</VirtualHost>
After applying the code and restarting apache, when I go to /example I get a 404 not found response.
When I test htaccess at (https://htaccess.madewithlove.be), the output is as https://www.test.com/example.html as I want. I wonder what the problem is.
RewriteCond %{HTTP_HOST} www.test.com
RewriteCond %{REQUEST_URI} /example
RewriteRule . https://www.test.com/example.html [R=303,L]
when I go to /example I get a 404 not found response.
Not sure if something has been lost in your exemplification, but from the rules as written, if you request /example it will result in a redirect-loop as it will continually redirect to /example.html again and again. (Unless you are actually making the request over HTTPS, in which case the directive isn't doing anything at all and you will indeed get a 404!)
This is because the second condition %{REQUEST_URI} /example also matches the target URL /example.html. You need to make the regex more specific and match only /example, not any URL that simply contains /example. This check can also be moved to the RewriteRule directive (the condition is not required). For example:
RewriteRule ^/example$ https://www.test.com/example.html [R=303,L]
The condition that checks the HTTP_HOST would not seem necessary, since these directives are in the vHost for www.test.com, so it cannot be any other hostname?
However, since this rule is in the vHost for port 80, it is only going to apply to HTTP requests (not HTTPS). If you are actually requesting https://www.test.com/example (ie. HTTPS) as would seem to be implied by your test results from the MWL tool, then the directive is never going to be processed and you will indeed get a 404.
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}
Your HTTP to HTTPS redirect is missing the last part so redirects everything to the homepage. The RewriteRule directive should read:
RewriteRule (.*) https://%{HTTP_HOST}$1 [R=301,L]
However, there's no point redirecting to HTTPS if all your directives are in the vHost:80 container.
This rule is also more complex than it needs to be. Since you are in the vHost:80 container, HTTPS is always going to be off - the check is redundant.
ServerName www.test.com
ServerAlias www.test.com
If you only have one hostname then you don't need two directives. Only the ServerName is required in this case.
When I test htaccess at (https://htaccess.madewithlove.be)
You don't have an .htaccess file here. You are using the directives directly in the vHost container, which is a different context. The directives behave slightly different here. For example, the RewriteRule pattern . (a single dot) has a different result here than when used in .htaccess. In a virtualhost context it is successful for every request, whereas in .htaccess it is successful for everything except the homepage (which is probably the intention here).
However, the MWL .htaccess tester only makes a "single" request (or single pass through the file). It does not "follow" redirects or make multiple passes through the file as it would do in a real server environment. So it cannot catch redirect/rewrite loops - which are a common cause of error.
The right part on RewriteRule is the destination file, try change :
RewriteCond %{REQUEST_URI} /example
To :
RewriteCond %{REQUEST_URI} /example.html

Forcing redirect 301 from any domain urls to one only subfolder

i have an old domain
www.olddomain.com
and i want to redirect to
www.newdomain.com/slug1
BUT
if a user types
www.olddomain.com/folderX
she gets
www.newdomain.com/slug1folderX
instead of simply
newdomain.com/slug1
which is wrong of course
how can i fix my apache? is it doable in the .conf files or htaccess?
UPDATE
this is my current virtual host .conf
<VirtualHost *:80>
ServerName olddomain.it
ServerAlias www.olddomain.it
Redirect 301 / https://www.newdomain.it/slug
</VirtualHost>
On old domain's site root .htaccess you can use this rule:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www\.)?olddomain\.com$ [NC]
RewriteRule ^ http://www.newdomain.com/slug1? [L,R=302]
Remember to clear your browser cache before testing this rule.

Apache Rewrite - Redirect Wildcard Subdomain and Handling Internal URL shortener

I have problem in redirecting wild-card sub-domain and handing internal URL shortener.
Let's say I have an internal URL shortener in my app
example.com/b/ABCDE
that will translate
example.com/book/12345678-the-book-name
the script referred by /b/ (I use PHP framework that could handle URL rule) will translate short ID ABCDE to the book real ID 12345678 (and the title "The Book Name") then redirect it the book's permanent URL example.com/book/12345678-the-book-name
so then every time I spread a link about a book in websites like bulletin boards, micro-blogging sites, or physical media like posters or business cards, I use the short link (the example.com/b/ABCDE) instead of the permanent link (example.com/book/12345678-the-book-name).
next, I need to redirect all wild-card sub-domain to the main domain (www.example.com) while maintaining the request URI, e.g.
http://random.example.com/book/11111111-some-book -> http://www.example.com/book/11111111-some-book
http://123456.example.com/book/22222222-another-book -> http://www.example.com/book/22222222-another-book
http://abcdefg.example.com/book/33333333-another-book-again -> http://www.example.com/book/33333333-another-book-again
by adding the rule below after all the rules I used
<VirtualHost *:80>
ServerName example.com
ServerAlias *.example.com
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www.example.com [NC]
RewriteRule ^/(.*)$ http://www.example.com/$1 [R=301]
</VirtualHost>
Consequently the url with example.com domain and without prefix like below
http://example.com/book/11111111-some-book
will translate to
http://www.example.com/book/11111111-some-book
And, another consequence is that if the internal URL shortener use plain domain without the prefix, it will take two redirection to resolve. For example,
http://example.com/b/ABCDE
will first be redirected to
http://www.example.com/b/ABCDE
which then be redirected to
http://www.example.com/book/12345678-the-book-name
Actually, I don't mind with the two-times redirection. But my SEO consultant said that the two-times redirection is bad for my site's SEO. (which I still don't know why)
So I tried change the last rule to below
<VirtualHost *:80>
ServerName example.com
ServerAlias *.example.com
RewriteEngine on
RewriteCond %{HTTP_HOST} ^example.com [NC]
RewriteCond %{REQUEST_URI} ^/b/(.*)$
RewriteRule . index.php [L]
RewriteCond %{HTTP_HOST} !^www.example.com [NC]
RewriteRule ^/(.*)$ http://www.example.com/$1 [R=301]
</VirtualHost>
I'm not very good at configuring Apache, but when I simulate above rule in http://htaccess.madewithlove.be/, it works. But when I applied it to my server, it gave me 400 Bad Request for the example.com/p/ABCDE.
So, my questions are
Is my SEO consultant right about his argument? Is there any explanation that can back him up or is there a counter-argument?
Why the server gave 400 Bad Request?
How to fix the redirection? I want to maintain the short URL (example.com/b/ABCDE without www prefix) but still in one redirection.
Is you SEO consultant right?
As all things SEO, the answer involves some guessing and assumptions, but he's probably right.
When you redirect a page, you tell the crawler to forget the initial page and come back later to index the target page instead, which introduces a delay between the first introduction of your page to the world and the actual appearance of your page in the search results. Two redirections means you double that delay. Depending on the "mood" of the search engine, that can add up to a significant regression in you SEO (or some confusion in your indexed urls while the search engine sorts the redirections).
Why you get a 400 response
If you check the documentation for RewriteRule, entry Inside per-server configuration
Given Rule --> Resulting Substitution
^/somepath(.*) --> otherpath$1 : invalid, not supported
^/somepath(.*) --> /otherpath$1 : /otherpath/pathinfo
which means that, in a vhost conf, you have to provide an absolute path for your substition (the final one that will be handed back to Apache, previous ones can be anything you like). To solve the 400 error:
RewriteRule . /index.php [L]
How to fix the redirection
It will depend on how your index.php builds its redirections, but setting
ServerName www.example.com
UseCanonicalName On
will set $_SERVER["SERVER_NAME"]to www.example.com and should result in a URL pointing to the canonical domain.
Potential conf
<VirtualHost *:80>
ServerName www.example.com
ServerAlias *.example.com example.com
UseCanonicalName On
RewriteEngine on
#set the document root
DocumentRoot /path/to/the/app
# if something goes wrong, setup logs to track what happens
# comment these lines when you're done
ErrorLog /a/path/to/a/log/file
RewriteLogLevel 5
RewriteLog /a/path/to/another/log/file
# I simplified the conditions, those are equivalent to your rules
# a RewriteRule tries to match against %{REQUEST_URI}
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^/b/ /index.php [L]
RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteRule ^/(.*)$ http://www.example.com/$1 [R=301]
</VirtualHost>

A simple mod_rewrite rule in my .htaccess to redirect a friendly URL to the script

hi i'd like to rewrite http://www.domain.com/site_reg/index.php to http://www.domain.com/signup how would I do this. both for www.domain.com and domain.com?
EDIT: maybe i have it backwards... user types in http://www.domain.com/signup and http://www.domain.com/site_reg/index.php load the page
This will work for both www.domain.com and domain.com, assuming you have ServerName and ServerAlias set in your VirtualHost
Try:
<VirtualHost>
ServerName domain.com
ServerAlias www.domain.com
RewriteEngine On
RewriteRule ^/site_reg/(.*) /signup/$1 [R=301,L]
</VirtualHost>
You want to assign a 301 Redirect to tell search engines, browsers, etc. that the page has permanently moved. If the move is not permanent, use the temporary status code: 307
Try:
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} !FeedBurner
RewriteRule ^site_reg\/index\.php$ http://www.domain.com/signup [R,L]
Put this in your base .htaccess:
RewriteEngine on
RewriteRule ^site_reg/index\.php$ http://www.domain.com/signup [R,L]

Need help configuring 301 permanent redirect in Apache for non www

I am trying to configure my Apache 2.2 version to use a 301 permanent redirect when someone types my url without the www. I want to configure this in the httpd.conf and not using .htaccess if possible. I have tried using Redirect permanent but the first variable has to be a directory and not a url. Any ideas how to configure boom.com requests to be redirected to www.boom.com using a 301 redirect in Apache? Thanks
Add the following:
# Canonical hostnames
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.boom\.com [NC]
RewriteCond %{HTTP_HOST} !=""
RewriteRule ^/(.*) http://www.boom.com/$1 [L,R=301]
This will redirect all request which don't match www.boom.com to www.boom.com, with the same query path. (For example, boom.com/foo?foo=bar will be redirect to www.boom.com/foo?foo=bar).
If you have named virtual hosts you could put the extra RewriteCond entries #tux21b gave inside to isolate them. Also if you have mod_alias you could try this which should do the same thing:
<VirtualHost boom.com:80>
RedirectMatch permanent /.* http://www.boom.com$0
</VirtualHost>
I'm sure someone will comment if there's a reason to use one over the other.