skip to Main Content

I have an Apache server that passes requests for all non existing resources to index.php to act as central controller. The htaccess rule for this is:

RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ /index.php [NC,L]

On this server I have two subdomains pointing at the same webroot directory:

www.example.com

and

booking.example.com

My client would like the booking section (/book) to served up using the booking subdomain, while the rest of the site should stay on www.

So they would like URLs such as

https://www.example.com/about-us

and

https://booking.example.com/book

This means that requests to https://booking.example.com/about-us need to be redirected to https://www.example.com/about-us, and along the same lines, request to https://www.example.com/book need to be redirected to https://booking.example.com/book.

Effectively they want the site sectioned off into two subdomains, served from the same system behind the scenes.

The first part (for /book onto booking) is achieved easily enough by simply adding this to htaccess:

# redirect all requests on www. made to /book to booking subdomain
RewriteCond %{HTTP_HOST} ^www.
RewriteRule ^book(.*)$ https://booking.example.com/book$1 [L,R=301]

The counterpart (send non /book requests to www) is easy enough as well:

# redirect all requests on booking. made to not /book to www subdomain
RewriteCond %{HTTP_HOST} ^booking.
RewriteCond %{REQUEST_URI} !^/book
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]

In simulation, this works exactly as intended:

https://htaccess.madewithlove.be?share=990cff3e-7739-5bff-912f-493ae76e3a4c

https://htaccess.madewithlove.be?share=a005713e-97bf-59af-b89a-f2c5ceae13ed

Problem is that the index.php redirect is messing this up and I don’t fully understand how.

If I only have one of the two rules active they work fine, respectively.

However, if I activate both and go to https://www.example.com and follow a link to https://www.example.com/book I end up at https://www.example.com/index.php instead of the expected https://booking.example.com/book.

As far as I can tell this is because after redirecting to the booking subdomain the REQUEST_URI check from the second rule, which looks for requests on booking for not /book, seems to have the value of REQUEST_URI down as index.php.

What I don’t get is why this second check looks at REQUEST_URI with that value – I would have assumed that the [L,R=301] from the first rule triggers a new request to the server that is evaluated as such but this does not seem to be the case.

Instead it appears that the internal resolution of the request to index.php is passed to the second rule.

How can I work around this?

EDIT:
For clarity – the rewrite section of the htaccess looks like this:

# redirect all requests on www. made to /book to booking subdomain
RewriteCond %{HTTP_HOST} ^www.
RewriteRule ^book(.*)$ https://booking.example.com/book$1 [L,R=301]

# redirect all requests on booking. made to not /book to www subdomain
RewriteCond %{HTTP_HOST} ^booking.
RewriteCond %{REQUEST_URI} !^/book
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]

RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ /index.php [NC,L]

2

Answers


  1. Chosen as BEST ANSWER

    Right so I got this to work by adding a RewriteRule for the the second redirect - booking to www for requests to not /book - to not trigger on /index.php.

    Also note that I added a rule to allow resources (js, css) to be loaded on the booking subdomain.

    # redirect all requests on www. made to /book to booking subdomain
    RewriteCond %{HTTP_HOST} ^www.
    RewriteRule ^book(.*)$ https://booking.example.com/book$1 [L,R=301]
    
    # redirect all requests on booking. made to not /book to www subdomain
    RewriteCond %{HTTP_HOST} ^booking.
    RewriteCond %{REQUEST_URI} !^/book
    RewriteCond %{REQUEST_URI} !^/index.php  #don't fire on index.php
    RewriteCond %{REQUEST_URI} !(.js|.css)   #allow js / css
    RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]
    
    RewriteCond %{REQUEST_FILENAME} -s [OR]
    RewriteCond %{REQUEST_FILENAME} -l [OR]
    RewriteCond %{REQUEST_FILENAME} -d
    RewriteRule ^.*$ - [NC,L]
    RewriteRule ^.*$ /index.php [NC,L]
    

  2. Try changing:

    RewriteCond %{REQUEST_URI} !^/book
    

    to

    RewriteCond %{THE_REQUEST} !s/book
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search