When setting up an Apache reverse proxy, there are cases where you need certain directories to bypass the proxy and be served directly from the local filesystem. A common scenario is when you want to:
- Proxy most requests to a backend application (e.g., Tomcat on port 8080)
- Serve static assets (images, CSS, JS) directly from the filesystem for better performance
- Maintain some legacy content outside the proxied application
The most effective approach is to use Location
or LocationMatch
directives to define exceptions:
<VirtualHost *:80>
ServerName localhost
# General proxy settings
ProxyRequests Off
ProxyPreserveHost On
ProxyTimeout 600
# Exception for /images
<Location /images>
ProxyPass !
</Location>
# Exception for specific file types
<LocationMatch "\.(jpg|png|gif|css|js)$">
ProxyPass !
</LocationMatch>
# Default proxy rule
ProxyPass / http://localhost:8080/myapp/
ProxyPassReverse / http://localhost:8080/myapp/
</VirtualHost>
For more complex routing logic, you can combine mod_rewrite with proxy rules:
RewriteEngine On
# Skip proxy for /images
RewriteRule ^/images - [L]
# Skip proxy for specific file patterns
RewriteCond %{REQUEST_URI} \.(css|js|jpg|png|gif)$ [NC]
RewriteRule ^ - [L]
# Proxy everything else
RewriteRule ^/(.*) http://localhost:8080/myapp/$1 [P,L]
When implementing proxy exceptions:
- Place more specific exceptions before general rules
- Use
LocationMatch
for pattern-based exclusions - Consider filesystem permissions for directly served content
- Benchmark with and without exceptions to verify performance gains
If exceptions aren't working as expected:
- Enable verbose logging with
LogLevel debug
- Check the order of directives in your config
- Verify filesystem permissions for excluded paths
- Test with
curl -v
to inspect headers and responses
When implementing reverse proxy configurations in Apache, a common requirement emerges: proxying most requests to a backend application while excluding specific directories that should be served directly from the local filesystem. This scenario frequently occurs when:
- Static assets (images, CSS, JS) should be served directly for performance
- Certain API endpoints need to bypass the proxy
- Admin interfaces require direct access
The existing setup shows a basic reverse proxy configuration:
ProxyRequests Off
ProxyTimeout 600
ProxyPreserveHost On
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
RewriteEngine On
RewriteRule ^/(.*) http://localhost:8080/VirtualHostBase/http/%{SERVER_NAME}:80/myapp/VirtualHostRoot/$1 [L,P]
To exclude the /images directory from being proxied, we need to modify the configuration. Here are three approaches:
Option 1: Using ProxyPass Exceptions
ProxyRequests Off
ProxyPreserveHost On
# Exclude /images from proxying
ProxyPass /images !
# Proxy all other requests
ProxyPass / http://localhost:8080/myapp/
ProxyPassReverse / http://localhost:8080/myapp/
Option 2: Combining ProxyPass with Location
<Location />
ProxyPass http://localhost:8080/myapp/
ProxyPassReverse http://localhost:8080/myapp/
</Location>
<Location /images>
ProxyPass !
DocumentRoot /var/www/html
</Location>
Option 3: Using mod_rewrite with Conditions
RewriteEngine On
# Skip proxy for /images
RewriteCond %{REQUEST_URI} ^/images [NC]
RewriteRule ^ - [L]
# Proxy all other requests
RewriteRule ^/(.*) http://localhost:8080/VirtualHostBase/http/%{SERVER_NAME}:80/myapp/VirtualHostRoot/$1 [P]
For multiple directory exceptions, regular expressions can be powerful:
ProxyPassMatch ^/(images|css|js) !
ProxyPass / http://localhost:8080/myapp/
ProxyPassReverse / http://localhost:8080/myapp/
When implementing proxy exceptions:
- Place frequent exceptions first in configuration
- Use simple pattern matching when possible
- Consider filesystem permissions for excluded directories
- Test with curl -v to verify request routing
Common issues and solutions:
Issue | Solution |
---|---|
Exceptions not working | Check directive order (exceptions must come before general rules) |
Permission denied | Verify DocumentRoot and Directory permissions |
Rewriting loops | Add [L] flags and test with RewriteLog |