How to Configure Apache Reverse Proxy with URL Path Removal for Karaf/Jetty Applications


7 views

When setting up Apache as a reverse proxy for Karaf-hosted applications (specifically Jetty servlets), we frequently encounter the need to:

  1. Hide the application context path (/jellyfish in this case)
  2. Maintain clean URLs at the proxy level
  3. Handle redirects properly without URL duplication

The current setup with ProxyPassMatch ^/(.*) http://granny-server:8181/jellyfish/$1 causes double-path issues because:

1. Initial request: /login
2. Proxy adds /jellyfish prefix → /jellyfish/login
3. Jetty responds with redirect containing full path /jellyfish/login
4. Proxy prepends another /jellyfish → /jellyfish/jellyfish/login

Here's a configuration that properly handles path manipulation:

<VirtualHost *:80>
    ServerName web-server
    
    # Essential proxy settings
    ProxyRequests Off
    ProxyPreserveHost On
    ProxyVia On
    
    # Local assets exclusion
    Alias /images/ "/var/www/images/"
    ProxyPass /images !
    
    # Main proxy configuration
    ProxyPass / http://app-server:8181/jellyfish/
    ProxyPassReverse / http://app-server:8181/jellyfish/
    
    # Special handling for redirects
    Header edit Location ^http://app-server:8181/jellyfish/(.*)$ http://web-server/$1
    
    # Security hardening
    <Proxy *>
        Require all granted
        Allow from all
    </Proxy>
    
    # Additional headers if needed
    RequestHeader set X-Forwarded-Proto "http"
    RequestHeader set X-Forwarded-Port "80"
</VirtualHost>

1. ProxyPass with Trailing Slash:
The trailing slash in ProxyPass / http://app-server:8181/jellyfish/ ensures proper path concatenation.

2. Header Editing:
The Header edit Location directive modifies redirect headers coming from the backend to maintain clean frontend URLs.

For cases requiring more complex routing:

RewriteEngine On
# Exclude static resources
RewriteCond %{REQUEST_URI} !^/images/.*$
# Proxy all other requests
RewriteRule ^/(.*)$ http://app-server:8181/jellyfish/$1 [P]
# Fix redirect headers
ProxyPassReverse / http://app-server:8181/jellyfish/
ProxyPassReverse / http://web-server/

After implementing, verify with:

  1. curl -v http://web-server/login (check Location headers)
  2. apachectl configtest
  3. Browser testing with developer tools open
  • Double slashes in URLs - always include/exclude trailing slashes consistently
  • SSL termination - remember to set X-Forwarded-Proto when using HTTPS
  • WebSocket support - may require additional proxy parameters

When implementing Apache as a reverse proxy for Karaf-hosted applications, we often need to clean up URLs by removing application context paths. The specific challenge arises when:

  • The backend application serves content under /jellyfish path
  • We want public URLs to appear as root-relative (/login instead of /jellyfish/login)
  • Proxy configurations accidentally duplicate the path component

The error messages showing /jellyfish/jellyfish/home indicate the path is being appended twice. This happens because:

ProxyPassMatch ^/(.*) http://granny-server:8181/jellyfish/$1
ProxyPassReverse / http://granny-server:8181/jellyfish

The ProxyPassMatch adds jellyfish to the path, then the backend application likely redirects with another jellyfish prefix, creating the duplicate.

Here's a tested solution that properly handles path rewriting:

<VirtualHost *:80>
    ServerName web-server
    
    RewriteEngine On
    # Security rule to prevent malicious proxy attempts
    RewriteCond %{REQUEST_URI} !^/
    RewriteRule .* - [R=400,L]
    
    # Exclude static assets from proxying
    ProxyPass /images !
    Alias /images/ "/var/www/images/"
    
    # Main proxy configuration
    ProxyPass / http://app-server:8181/jellyfish/
    ProxyPassReverse / http://app-server:8181/jellyfish/
    
    # Handle redirects from the backend
    ProxyPassReverseCookiePath /jellyfish /
    
    # Required for proper host header handling
    ProxyPreserveHost On
    
    <Directory "/var/www/images">
        Options Indexes MultiViews FollowSymLinks
        Require all granted
    </Directory>
</VirtualHost>

Path Handling: The trailing slashes in both ProxyPass and ProxyPassReverse are critical for proper path resolution.

Cookie Path Adjustment: ProxyPassReverseCookiePath ensures session cookies work correctly when paths are rewritten.

Alternative Using mod_rewrite: For more complex scenarios, you could use:

RewriteRule ^/(.*)$ http://app-server:8181/jellyfish/$1 [P]
ProxyPassReverse / http://app-server:8181/jellyfish
  • Enable LogLevel debug temporarily to trace rewrite/proxy behavior
  • Check both Apache access logs and backend application logs
  • Test with curl -v to observe redirects and headers
  • Verify the backend isn't generating absolute URLs with the context path