CaptainStiggz
CaptainStiggz

Reputation: 1907

Apache multiple rewrite conditions for a single rule

SOLVED: The problem was related to Symfony. See my answer below.

I recently changed the domain of my site, and I'd like to permanently redirect visitors to the new domain, excluding a few specific URLs that must remain accessible via the old domain. Here's what I tried. The issue is that redirection occurs, but the specified directories are not excluded.

RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example1/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example2/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example3/.*$ [NC]
RewriteCond %{REQUEST_URI} !/examplepage.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com%{REQUEST_URI} [R=301,L]

I also tried placing the following at the top of my configuration file, no luck.

RewriteRule ^(example1|example2|example3)($|/) - [L]

Edit: It's also worth noting that these directives seem to work for examplepage.html, it's just the "directories" that don't work. This is Apache 2.4.7

The following example URLs should all be left out of the rewriting process (so pretty much anything containing "/example1":

https://olddomain.com/example1
https://olddomain.com/example1/action1
https://olddomain.com/app.php/example1/action1

For the sake of completeness, the above directives are in my apache.conf file. In addition, Symfony2 provides a default .htaccess file with the following rewrite directives. Could there be some sort of contradiction here?

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the app.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]

# Redirect to URI without front controller to prevent duplicate content
# (with and without `/app.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
#   following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]

# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]

# Rewrite all other queries to the front controller.
RewriteRule .? %{ENV:BASE}/app.php [L]

Upvotes: 0

Views: 1727

Answers (2)

CaptainStiggz
CaptainStiggz

Reputation: 1907

I figured it out. If anyone else runs into a similar issue, the problem is due to Symfony issuing an [INTERNAL REDIRECT] on all URLs to /app.php. /app.php is then passed through the gauntlet of rewrite conditions for a second round. Excluding app.php in your rewrite conditions will solve it.

RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/example1/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/example2/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/example3/.*$ [NC]
RewriteCond %{REQUEST_URI} !/app.php [NC]
RewriteCond %{REQUEST_URI} !/examplehtml.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com/$1 [R=301,L] 

Upvotes: 0

Michael Oryl
Michael Oryl

Reputation: 21662

Try this instead:

RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/example1 [NC]
RewriteCond %{REQUEST_URI} !^/example2 [NC]
RewriteCond %{REQUEST_URI} !^/example3 [NC]
RewriteCond %{REQUEST_URI} !/examplepage.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com/$1 [R=301,L]

I think you are making the folder conditions overly complex. Also note that you can use $1 in the last line to just carry over the value caught in the () in the left side of the line. Makes no difference in this example, but would if you needed only part of the left hand side to be used in the destination URL on the right.

Upvotes: 1

Related Questions