When migrating applications or restructuring endpoints, we often need to modify URL paths while preserving the original query parameters. The standard approach using path_dir
and set-path
might not work as expected due to HAProxy's path processing behavior.
Here's what typically doesn't work:
acl old_name path_dir -i /old_name
http-request set-path /new_name/%[query] if old_name
This would transform /old_name/Default.aspx?Id=123
into /new_name/?Id=123
, losing the actual file path component.
We need to capture both the base path and subsequent path components. Here's the correct approach:
acl is_old_path path_beg -i /old_name/
http-request set-path /new_name%[path,regsub(^/old_name/,/)] if is_old_path
This solution:
- Uses
path_beg
for more precise matching - Preserves the query parameters automatically
- Maintains the file path after the base directory
For a production-ready setup:
frontend http_in
bind *:80
acl is_old_path path_beg -i /old_name/
http-request redirect code 301 location /new_name%[path,regsub(^/old_name/,/)] unless { path_beg -i /new_name/ }
http-request set-path /new_name%[path,regsub(^/old_name/,/)] if is_old_path
use_backend app_servers
backend app_servers
server s1 192.168.1.10:8080 check
For complex rewrites with multiple path components:
http-request set-path /new_name/v2%[path,regsub(^/old_name/v1/,/)] if { path_beg -i /old_name/v1/ }
This handles versioned API endpoints while maintaining all URL components.
Always verify your configuration with:
haproxy -c -f /etc/haproxy/haproxy.cfg
And test with curl:
curl -v "http://localhost/old_name/Default.aspx?Id=123"
When migrating applications with renamed endpoints in HAProxy, we often need to modify just part of the URL path while preserving all query parameters. A common case is when an application changes its base path from /old_name
to /new_name
but maintains the same file structure and query parameters.
The configuration you tried:
acl old_name path_dir -i /old_name
http-request set-path /new_name/%[query] if old_name
has several issues:
%[query]
only includes the query string (everything after ?)- It completely replaces the path instead of modifying part of it
- The original path components after /old_name/ are lost
Here's the correct approach using HAProxy 1.8+ syntax:
acl is_old_path path_beg -i /old_name/
http-request replace-path /old_name/(.*) /new_name/\1 if is_old_path
For HAProxy 2.0+, you can use more advanced regex:
http-request replace-path ^/old_name(/.*)?$ /new_name\1 if { path_beg /old_name/ }
Here's a full frontend configuration that handles the redirection:
frontend http-in
bind *:80
acl is_old_path path_beg -i /old_name/
# Option 1: Simple path replacement
http-request replace-path /old_name/(.*) /new_name/\1 if is_old_path
# Option 2: Alternative using regex capture (HAProxy 2.2+)
# http-request replace-path ^/old_name(/.*)?$ /new_name\1 if is_old_path
# Send to backend
use_backend app_servers if { path_beg /new_name/ }
default_backend app_servers
The above configuration will transform:
http://www.site.com/old_name/Default.aspx?Id=123
into:
http://www.site.com/new_name/Default.aspx?Id=123
while preserving all path components after /old_name/ and all query parameters.
For more complex scenarios:
- Multiple path changes: Chain multiple replace-path rules
- Host-based routing: Combine with req.hdr(host) conditions
- 301 Redirects: Use 'redirect' instead for permanent changes