0

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.

1
+50

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

  • Thank you for the reply. The old was blogs.example.com and the new is www.example.com/blog. With that reversal, you see that your example and mine in the question are almost identical. And really, the RewriteRule was an add-on to try to handle the odd results from Redirect. Still can't figure out why Redirect doesn't work by itself. I'm using 302 temporary redirects during testing so the browser doesn't cache the (incorrect) redirects--it reduces the need to clear the browser cache. If I could get it working, I'd switch to 301s. – Mark Berry May 26 '15 at 16:55
  • Don't want the bounty to go to waste so awarding it as a thank-you for replying. – Mark Berry May 26 '15 at 22:03
  • Thanks for generosity Mark. The big difference in our examples is the NOT logic. You are matching anything at 'blog.example.com/blog' but I find more effective to match Anything that is not the ultimate result, which means use a NOT match. I have had unanimous success with this approach and would love to find where your trouble is... With the 2 lines I suggested, is it still not redirecting properly ? What is the result ? – devinstetler May 27 '15 at 3:36
  • Okay I think I see what you mean. It was confusing since blogs.example.com no longer exists, so why redirect to it? I tried using the NOT logic with www.example.com/blog but got an infinite redirect loop (see updated question). This also breaks my main site: www.example.com now gives an infinite redirect loop as well (goes to www.example.com/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/blog/). – Mark Berry May 27 '15 at 15:37
  • you are confusing a couple things. the mod_rewrite var HTTP_HOST is just the host, so if you are trying to match "/blog" it will NEVER be true and keep redirecting to /blog, hence the infinite loop. I had it reversed, thinking blogs.example was your NEW site. I edited my answer to reflect your actual situation. Since blogs.example.com no longer exists, this will redirect all incoming blogs.example.com traffic to www.example.com and retain everything after the .com. Of course, your webserver will still need to be accepting requests for blogs.example.com for this to work. – devinstetler May 27 '15 at 17:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.