Redirect to absolute URL in .htaccess returns wrong host name on OpenShift

I'm setting up a web site on OpenShift. It runs under Apache 2.2.15, but I do not have access to the Apache root or logs so I am trying to emulate virtual directories in an .htaccess file at the root of my site. Most of it is working well but there is a redirect issue I can't figure out.

The site is structured like this:

app-root/repo - the site root where .htaccess is located
app-root/repo/domain_example
app-root/repo/domain_example/main - main web site (WordPress)

In WordPress, my blog is under www.example.com/blog, but before migrating to WordPress, I had several articles in a blogs.example.com subdomain. To maintain links, I set up Redirect commands in .htaccess. They worked fine at my old shared hosting provider. They even worked fine at OpenShift before I added the www.example.com as an OpenShift alias. However since adding the alias, I can't force .htaccess to return www. if the original hostname starts with blogs.

From the Apache Redirect documentation:

The new URL should be an absolute URL beginning with a scheme and hostname. In Apache HTTP Server 2.2.6 and later, a URL-path beginning with a slash may also be used, in which case the scheme and hostname of the current server will be added. Then any request beginning with URL-path will return a redirect request to the client at the location of the target URL.

What I expect: If I provide an absolute URL as a target, the redirect should return that URL to the client. The client can then re-issue its request using the correct URL.

What is happening: The redirect is happening (I see the 302 in Firebug), but it points to the source domain, not the target. It's like it's doing the second bit (using the "scheme and hostname of the current server") even though I have provided an absolute URL.

Here is an excerpt of my .htaccess:

Options +FollowSymLinks -MultiViews
RewriteEngine On
RewriteBase /

# This section from https://my.bluehost.com/cgi/help/347#redirect
RewriteCond %{HTTP_HOST} ^(www.)?example\.com$
RewriteCond %{REQUEST_URI} !^/domain_example/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /domain_example/main/$1
RewriteCond %{HTTP_HOST} ^(www.)?example\.com$
RewriteRule ^(/)?$ domain_example/main/index.php [L] 

# blogs.example.com redirects

redirect 302 /mark/post/Check-Windows-Time-Settings.aspx http://www.example.com/blog/2010/05/check-windows-time-settings/

With that .htaccess, when I browse to http://blogs.example.com//mark/post/Check-Windows-Time-Settings.aspx and view the response in Firebug, I see that the 302 redirect is going to http://blogs.example.com/blog/2010/05/check-windows-time-settings/. But that doesn't exist, so I get a 404 Not Found. Why is it going to blogs. when I tell it to go to www. ?

I wondered if the OpenShift alias is somehow overriding the Redirect, but according to the Redirect documentation:

Redirect directives take precedence over Alias and ScriptAlias directives, irrespective of their ordering in the configuration file.

I also tried adding an explicit trap and rewrite for a path that starts with blogs.example.com/blog/ (which is what the redirect is apparently returning):

RewriteCond %{HTTP_HOST} ^blogs\.example\.com/blog/ [NC]
RewriteRule ^(.*)$ http://www.example.com/blog/$1 [L,R=302]

I still get the 404 Not Found with that. In fact, even the most basic URL, http://blogs.example.com/blog/, gives a 404.

How do I get redirects to work in this situation?

Update 27 May 2015 #1

Tried using "not" logic in the Rewrite block:

RewriteCond %{HTTP_HOST} !^www\.example\.com/blog/ [NC]
RewriteRule ^(.*)$ http://www.example.com/blog/$1 [L,R=302]

This leads to an infinite redirect loop, 20 redirects before it gives up. Each redirect still begins with http://blogs.example.com so something is still preventing the RewriteRule from writing the "www" at the beginning of the URL.

Same results if I terminate the NOT logic with a $:

RewriteCond %{HTTP_HOST} !^www\.example\.com/blog/$ [NC]
RewriteRule ^(.*)$ http://www.example.com/blog/$1 [L,R=302]

Update 27 May 2015 #2

@Quasidynamic pointed out that %(HTTP_HOST) only includes the hostname and nothing after. So I tried this to select only URLs starting with www.example.com/blog:

RewriteCond %{HTTP_HOST} ^blogs\.example\.com$ [NC]
RewriteCond %{REQUEST_URI} ^/blog/$ [NC]
RewriteRule ^(.*)$ http://www.example.com/blog/$1 [R=302,L]

No infinite loop, but the Redirect still goes to blogs., then the Rewrite fails to send it to www..

Update 28 May 2015

Per @Quasidynamic's request, trying this block:

RewriteCond %{HTTP_HOST} ^blogs\.example\.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/blog/$1 [R=302,L]

As expected by now, when I browse to blogs.example.com, it is redirected to blogs.example.com/blog/. Because that still matches the RewriteCond, it is then redirected to blogs.example.com/blog/blog/. Ad infinitum. It never, ever goes to www.example.com, which is the root problem I've had from the beginning: once I added blogs.example.com as an OpenShift subdomain, I can no longer use .htaccess to redirect to www.example.com no matter what I try.


Solution 1:

If your [old] is blogs.example.com and [target] is www.example.com/blog:

RewriteCond %{HTTP_HOST} blogs.example.com$ RewriteRule ^(.*)$ http://www.example.com/blog/$1 [R=301,L]

You were close, but you were trying to match /blog on the request which won't be there, that's only on the [target] site, as I understand your situation.

Use code 301 - "Status 301 means that the resource (page) is moved permanently to a new location. The client/browser should not attempt to request the original location but use the new location from now on." from

https://stackoverflow.com/questions/1393280/http-redirect-301-permanent-vs-302-temporary