2

I'm trying to configure a vhost to work with a proxy, but only if the request is not for a static file -- in which case I'd like Apache to serve it. Here's what I'm using:

<VirtualHost *:80> ServerName app.local DocumentRoot "/app/static" # Serve static files <Directory "/app/static"> Require all granted Options Indexes FollowSymLinks AllowOverride None </Directory> RewriteEngine On RewriteCond %{REQUEST_FILENAME} -f RewriteRule ^ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^/(.*) http://localhost:8000/$1 [P,L,QSA] ProxyPreserveHost On ProxyPass / http://localhost:8000/ ProxyPassReverse / http://localhost:8000/ </VirtualHost> 

Yet, if I try to get app.local/style.css then this request is still proxied (I see it in the proxy server log) despite the file /app/static/style.css existing. How can I make it serve these files?

1 Answer 1

2
RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^/(.*) http://localhost:8000/$1 [P,L,QSA] 

When you use mod_rewrite directives in a virtualhost context they are processed before the request has been mapped to the filesystem. Consequently, the REQUEST_FILENAME server variable has not yet been evaluated and simply contains the root-relative URL-path, not the absolute file-path. So, the condition in your first rule will always fail and the negated condition above will always be successful (unless you happen to have an abs file-path that matches the URL-path - unlikely).

Instead, you can either use a lookahead (eg. %{LA-U:REQUEST_FILENAME}), or manually construct the absolute filename using the DOCUMENT_ROOT and REQUEST_URI (URL-path) server variables. For example:

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f RewriteRule ^/(.*) http://localhost:8000/$1 [P] 

Incidentally, you don't need your first rule when you have the second since they are mutually exclusive.

The L and QSA flags are also superfluous here since P implies L and the query string is automatically appended when you don't explicitly include a query string in the substitution.

ProxyPass / http://localhost:8000/ 

You should also remove the ProxyPass directive since that will result in every URL being proxied. You are using mod_rewrite (with the P flag) instead to proxy the request.

2
  • Thank you very much. Makes sense, and worked flawlessly. Do I need to keep ProxyPassReverse or can I remove it as well? Commented Jan 25 at 21:09
  • 1
    @winck You should still keep the ProxyPassReverse directive. Although this is primarily only relevant if the target server triggers an external redirect. In this case, without the ProxyPassReverse directive, the target URL http://localhost:8000/... could be exposed, breaking the proxy. Commented Jan 25 at 21:19

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.