When working with HAProxy as a load balancer, we often need to route requests to different backend servers based on URI patterns. In this scenario, we need to distinguish between two types of requests:
http://example.com/answers/submit
http://example.com/tag-02/answers/submit
The key difference is the presence of /tag-02/
in the path. We'll use HAProxy's ACL (Access Control List) feature combined with the path_beg
matching method to implement this logic.
Here's the complete configuration that implements the routing logic:
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
frontend http-in
bind *:80
acl has_tag path_beg /tag-02/
use_backend tagged_backend if has_tag
default_backend default_backend
backend default_backend
balance roundrobin
server server1 192.168.1.10:80 check
server server2 192.168.1.11:80 check
backend tagged_backend
balance roundrobin
server server3 192.168.1.12:80 check
server server4 192.168.1.13:80 check
The critical part of this configuration is in the frontend
section:
acl has_tag path_beg /tag-02/
use_backend tagged_backend if has_tag
default_backend default_backend
This creates an ACL named has_tag
that matches any request where the path begins with /tag-02/
. The path_beg
matching method is perfect for our use case as it checks the beginning of the URL path.
HAProxy offers several path matching options depending on your needs:
# Exact path match
acl exact_match path /exact/path
# Beginning of path (what we used)
acl path_beg_match path_beg /prefix
# Directory-like match (contains)
acl path_dir_match path_dir /directory
# Regular expression match
acl path_regex_match path_reg ^/regex/pattern
After implementing the configuration, test it with curl commands:
# This will go to default_backend
curl http://example.com/answers/submit
# This will go to tagged_backend
curl http://example.com/tag-02/answers/submit
When using ACLs for routing:
path_beg
is generally faster than regex matches- Place more frequently matched ACLs first
- Consider using
path_dir
if you need to match a whole directory structure - For complex routing, combine multiple ACLs with logical operators
You can extend this approach with additional conditions:
frontend http-in
bind *:80
acl has_tag path_beg /tag-02/
acl is_api path_beg /api/
acl is_post method POST
# Route /tag-02/api/ POST requests to special backend
use_backend special_api_backend if has_tag is_api is_post
# Default routing rules
use_backend tagged_backend if has_tag
default_backend default_backend
When working with HAProxy, a common requirement is to route traffic based on specific patterns in the request URI. In this scenario, we need to direct requests either to backend server A or B depending on whether the URI contains the '/tag-02/' substring.
Here's the fundamental structure of our HAProxy configuration:
frontend http_in
bind *:80
mode http
# Routing rules will go here
default_backend default_backend
backend backend_a
server server1 192.168.1.10:80 check
backend backend_b
server server2 192.168.1.11:80 check
backend default_backend
server server3 192.168.1.12:80 check
The key to solving this is using ACLs (Access Control Lists) with path pattern matching:
frontend http_in
bind *:80
mode http
# Define ACL for our specific path pattern
acl has_tag_02 path_sub /tag-02/
# Route based on ACL
use_backend backend_b if has_tag_02
use_backend backend_a if !has_tag_02
default_backend default_backend
HAProxy offers several ways to match path patterns. Here are three common approaches:
# Method 1: Exact path match
acl is_exact_path path /answers/submit
# Method 2: Path begins with
acl starts_with_path path_beg /tag-02/
# Method 3: Regular expression match
acl regex_path path_reg ^/tag-[0-9]+/
Here's a full configuration file demonstrating the solution:
global
log /dev/log local0
log /dev/log local1 notice
daemon
maxconn 256
defaults
log global
mode http
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend http_front
bind *:80
acl has_tag path_sub /tag-02/
use_backend tag_backend if has_tag
default_backend main_backend
backend main_backend
balance roundrobin
server main1 10.0.0.1:80 check
server main2 10.0.0.2:80 check
backend tag_backend
server tag1 10.0.0.3:80 check
server tag2 10.0.0.4:80 check
When implementing path-based routing:
- path_beg is generally faster than path_sub
- For complex patterns, consider using maps for better performance
- Too many ACLs can impact performance - keep them minimal
After implementing, test with these curl commands:
# Should go to backend_a
curl http://localhost/answers/submit
# Should go to backend_b
curl http://localhost/tag-02/answers/submit
If you have multiple tags to handle, consider using maps:
frontend http_front
bind *:80
use_backend %[path,map(/etc/haproxy/tag_map.map)] if { path,map(/etc/haproxy/tag_map.map) -m found }
default_backend main_backend
With tag_map.map containing:
/tag-01/ tag_backend
/tag-02/ tag_backend
/special/ special_backend