When migrating applications behind reverse proxies, path handling often causes headaches. In this case, we have:
- Original app running at
localhost:10001
- Need to serve it under
/ds
path - Hardcoded script references at
/scripts
that must transparently map to/ds/scripts
The configuration attempt had two key issues:
RewriteRule /^scripts/(.*)$ /ds/scripts/$1 [L,PT]
- The
^
anchor in the pattern won't work in per-directory context (inside VirtualHost) - The rule needs proper flags for proxy integration
Here's the corrected VirtualHost setup:
<VirtualHost *:80>
ServerName hostname.example.com
# Enable rewrite engine
RewriteEngine On
# Catch script requests before proxying
RewriteCond %{REQUEST_URI} ^/scripts/ [NC]
RewriteRule ^/scripts/(.*) /ds/scripts/$1 [PT,L]
# Proxy configuration
ProxyPass /ds/ http://127.0.0.1:10001/
ProxyPassReverse /ds/ http://127.0.0.1:10001/
# Optional: Prevent direct access to backend
ProxyPass / http://127.0.0.1:10001/ !
</VirtualHost>
RewriteCond: The condition ensures we only rewrite actual script paths
[PT] flag: Passes the rewritten URI through to subsequent processing (needed for ProxyPass)
[L] flag: Makes this the last rule if it matches
ProxyPass ! directive: Prevents direct backend access (security best practice)
Verify with curl commands:
# Should proxy to backend
curl -I http://hostname/ds/
# Should rewrite and proxy
curl -I http://hostname/scripts/main.js
# Should return 403 (blocked by ProxyPass !)
curl -I http://hostname/
For simpler cases, you might prefer:
<Location /scripts>
ProxyPass http://127.0.0.1:10001/ds/scripts
ProxyPassReverse http://127.0.0.1:10001/ds/scripts
</Location>
Enable verbose logging in httpd.conf:
LogLevel debug
RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 3
Check for common pitfalls:
- Ensure mod_rewrite and mod_proxy are loaded
- Verify DocumentRoot isn't interfering
- Check for conflicting .htaccess files
When setting up a reverse proxy for an application running on port 10001, we need to serve it under /ds
path while handling hardcoded script references to /scripts
. The challenge is to rewrite /scripts
requests to /ds/scripts
before they reach the proxied application.
Here's the initial VirtualHost configuration that didn't work as expected:
<VirtualHost *:80>
RewriteEngine on
RewriteRule /^scripts/(.*)$ /ds/scripts/$1 [L,PT]
ProxyPass /ds/ http://127.0.0.1:10001/
ProxyPassReverse /ds/ http://127.0.0.1:10001/
</VirtualHost>
The main problems with the initial configuration are:
- The
^
anchor in the RewriteRule pattern is incorrect - it should not include the leading slash - The
PT
(passthrough) flag is appropriate, but the pattern matching needs adjustment - The rewrite rule should come before the ProxyPass directives
Here's the corrected configuration:
<VirtualHost *:80>
ServerName hostname
RewriteEngine On
RewriteRule ^/scripts/(.*) /ds/scripts/$1 [PT]
ProxyPass /ds/ http://localhost:10001/
ProxyPassReverse /ds/ http://localhost:10001/
# Optional: Handle requests to /scripts without trailing slash
RewriteRule ^/scripts$ /ds/scripts/ [R=301,L]
</VirtualHost>
- The
^/scripts/(.*)
pattern correctly matches requests starting with/scripts/
[PT]
flag ensures the rewritten URL is passed to the next processing phase (ProxyPass)- The order of directives is crucial - RewriteRules must come before ProxyPass
- ProxyPassReverse handles redirects from the backend application
After implementing these changes, test with:
curl -I http://hostname/scripts/somefile.js
curl -I http://hostname/ds/scripts/somefile.js
Both should return the same content from your backend application.
For more complex scenarios, you might need:
# Handle various script extensions
RewriteRule ^/scripts/(.*\.(js|css|png))$ /ds/scripts/$1 [PT]
# Exclude certain paths from rewriting
RewriteCond %{REQUEST_URI} !^/scripts/excluded/
RewriteRule ^/scripts/(.*) /ds/scripts/$1 [PT]
Enable rewrite logging for troubleshooting:
RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 3
Remember to turn this off in production environments.