1

I tried to perform a redirect writing in .htaccess file:

RewriteEngine on
RewriteRule article-1 www.another-site.com/article-1 [R=301,L,NC]

and it works correctly. Anyway, when I add a rewrite condition, for example:

RewriteEngine on
RewriteCond %{HTTP_REFERER} domain.tracker.com [NC]
RewriteRule article-1 www.another-site.com/article-1 [R=301,L,NC]

the redirect is no longer performed as if the condition was always evaluated as false. The referrer is correctly evaluated (I tried to redirect to www.site.com?ref=%{HTTP_REFERER} and I got www.site.com?ref=https://domain.tracker.com/?queries=vals, which is the correct referrer).

The only other rewrite instruction I have in .htaccess file is

#BEGIN WORDPRESS    
<IfModule mod_rewrite.c>
    RewriteRule ^index\.php$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]
    </IfModule>
#END WORDPRESS

Why are the conditions not working? Could it be a conflict with WordPress instruction? Could it depend by the hosting provider?

Arthu83
  • 11
  • 1
  • 2
  • 1
    "`www.another-site.com/article-1`" - Is `www.another-site.com` intended to be a hostname or a subdirectory? Where are these directives in relation to the WordPress code block? (Didn't you ask a nearly identical question the other day?) – MrWhite Sep 19 '18 at 21:51
  • Yes sorry, I was aware of the fact that the question wasn't so clear so I deleted it. Anyway, it is a different hostname (another domain that I own). The WordPress directives are at the bottom of the .htaccess file, while I've put mine at the top. – Arthu83 Sep 20 '18 at 09:35
  • "it is a different hostname" - Ok, that's what I assumed, however, if that's the case then the directive as posted cannot possibly "work correctly" because the `RewriteRule` _substitution_ is missing a _scheme_ (eg. `http://`). Instead, mod_rewrite will see it as a _subdirectory_ and without a `RewriteBase` directive the redirect will be wholly invalid. Is this really an example of your actual `.htaccess` code? (The order of your directives sounds correct.) – MrWhite Sep 20 '18 at 09:52
  • I tried both with and without the instruction 'RewriteBase \'. In any case, the redirect works correctly, but it stop doing it when I add a RewriteCond. So I guess the problem is not with the rewrite rule but with the condition. – Arthu83 Sep 20 '18 at 14:01
  • The `RewriteBase` directive was only if this was intended to be a subdirectory off the document root. "the redirect works correctly" - Well, this only compounds the mystery - because with the directives you've posted in the question, that's _impossible_. This isn't something that can simply be ignored as it perhaps implies that "something else" is triggering the redirect you are seeing. (?) Bear in mind also that 301 redirects are cached persistently by the browser (better to test with 302s), so you may not be seeing up-to-date results after a code change. – MrWhite Sep 21 '18 at 00:43
  • 1
    I always clear the cache before any test. "with the directives you've posted in the question, that's impossible" - Would you mind to post an explicit example of a correct redirect? I want to redirect from an article in my site to another different domain, only if the referrer is domain.tracker.com. Write it as an answer instead of a comment so I can mark it as the answer to my question. – Arthu83 Sep 22 '18 at 10:48
  • Answer posted. Hope it helps! :) – MrWhite Sep 23 '18 at 22:41

1 Answers1

1

The WordPress directives are at the bottom of the .htaccess file, while I've put mine at the top.

That is correct.

RewriteCond %{HTTP_REFERER} domain.tracker.com [NC]

There is nothing actually wrong with the RewriteCond directive you posted that would prevent this from working. The condition is successful if the HTTP Referer header contains the string "domain.tracker.com" (case-insensitive). That's it, there is nothing more to it. Bear in mind that the CondPattern is a regex, so the dots (.) need to be backslash-escaped in order to match literal dots, otherwise they match any character (which is the case in your example). So, your directive is potentially matching too much, but it's not going to stop it from working. eg. It would also match an HTTP Referer of the form: http://example.com/domain-tracker-com/foo.

The most common cause of such a condition not working is when the HTTP_REFERER does not contain what you expect. As you are no doubt aware, the Referer header is notoriously unreliable: it can be blocked by the client and/or website and is easily faked. Although your test appears to show the Referer being passed as expected, so that is a mystery.

RewriteRule article-1 www.another-site.com/article-1 [R=301,L,NC]

HOWEVER, the RewriteRule substitution (ie. www.another-site.com/article-1) is invalid in this context and will not result in the redirect as stated, ie. to the external host www.another-site.com. You are missing the required scheme (eg. http) and should be of the form: http://www.another-site.com/article-1. In other words, an absolute URL.

(I wondered if this was simply a typo in your question, since you had used an absolute URL in a related question on SO, but you appear to have confirmed in comments that it is correct as written.)

When the RewriteRule substitution does not start with a scheme (http or https) or slash (/) then it is seen as a relative URL-path. In per-directory .htaccess files, that means that it is seen as relative to the filesystem directory that contains the .htaccess file, which is called the "directory-prefix" (unless a RewriteBase directive states otherwise or the directives are being "inherited"). This directory-prefix is added back to the substitution at the end of the rewriting process. In the case of the above RewriteRule this would most probably result in a wholly invalid redirect of the form:

http://example.com/home/user/public_html/www.another-site.com/article-1

Where /home/user/public_html/ is the directory-prefix, ie. the absolute filesystem path of the location of the .htaccess file. example.com is the current host (probably the Host that has been requested). www.another-site.com/article-1 is the relative URL-path as stated in the RewriteRule substitution.

As stated above, you need to include the scheme/protocol to form an absolute URL:

RewriteCond %{HTTP_REFERER} domain\.tracker\.com [NC]
RewriteRule article-1 http://www.another-site.com/article-1 [R=301,L,NC]

Also note that the regex article-1 matches the string "article-1" anywhere inside the requested URL. eg. /foo-article-1-bar/ would also match. If you are matching a specific URL then you should match that specific URL, eg. ^article-1$. If the URL-path on the destination site is the same, then you can avoid repetition by capturing the URL-path and using a backreference in the RewriteRule substitution. For example:

RewriteRule ^(article-1)$ http://www.another-site.com/$1 [R=301,L,NC]

Why are the conditions not working?

From the information given, there is no reasonable explanation.

Could it be a conflict with WordPress instruction?

By placing these directives before the WordPress front-controller you have pretty much eliminated that possibility.

Could it depend by the hosting provider?

That is very unlikely.


Try this with a simple query string instead:

RewriteCond %{QUERY_STRING} ^bar=1$
RewriteRule ^(foo)$ http://example.com/$1 [R,QSD,L]

Request:

/foo?bar=1

And you should be temporarily (302) redirected to:

http://example.com/foo

ie. the same URL-path, but with the query string removed.

MrWhite
  • 11,643
  • 4
  • 25
  • 40