Learn HAProxy - Content Switching & ACLs
Episode 16 of 23

Learn HAProxy - Content Switching & ACLs

This episode masters the art of content switching: advanced ACL expressions, combining host, path, header, and payload conditions into a single decision, and structuring complex frontend logic that stays easy to understand.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Content switching is the ability to decide a destination based on the request's contents — not just IP and port. This is where ACLs evolve from simple conditions into a complete logical language.

Episode 16 covers advanced ACL expressions, how to combine many conditions into a single decision, and how to structure strong frontend logic without making the configuration file hard to read.

Advanced ACL Expressions

Converting Values with Fetches and Transforms

ACLs can process raw values with transformations. Example: comparing the API version from the path:

ACLs with regex and conversion
frontend api_front
    bind *:443 ssl crt /etc/haproxy/certs/fullchain.pem
    mode http
 
    acl api_v1 path_reg ^/v1/
    acl api_v2 path_reg ^/v2/
    acl is_json req.hdr(Content-Type) -i application/json
 
    use_backend v1_back if api_v1
    use_backend v2_back if api_v2
    default_backend v1_back

acl api_v1 path_reg ^/v1/ uses a regex to match a path prefix. Regexes give a flexibility path_beg can't offer.

Sampling the Request Payload

Some decisions require looking at the beginning of the request body:

Match the request payload
frontend api_front
    bind *:80
    mode http
 
    acl req_payload_ok req.payload(0,32) -m reg \
        "^\s*\{\s*\"name\""
    http-request deny deny_status 400 if !req_payload_ok
    default_backend api_back

req.payload(0,32) -m reg takes the first 32 bytes of the body and matches them against a JSON pattern. This is an example of content switching based on real contents.

Operations on Converted Values

Chained transformations allow finer logic:

Convert a header to a number
frontend web_front
    bind *:80
    mode http
 
    acl high_priority hdr(priority),lower -m str high
    acl small_room hdr(x-body-size),int gt 10000
 
    http-request deny deny_status 413 if !high_priority small_room
    default_backend web_back

hdr(priority),lower -m str high lowercases the header, then compares it; hdr(x-body-size),int gt 10000 converts the header value to an integer before comparing.

Combining ACLs for Complex Decisions

Logical Operators in a Single Condition

Conditions in use_backend and http-request support or, and, and !:

Combining conditions in one decision
frontend web_front
    bind *:80
    mode http
 
    acl host_app1 hdr(host) -i app1.example.com
    acl host_app2 hdr(host) -i app2.example.com
    acl is_api path_beg /api
    acl is_vip hdr(x-client-type) -i premium
 
    use_backend premium_back if is_vip and is_api
    use_backend app1_back if host_app1 and !is_api
    use_backend app2_back if host_app2
    default_backend web_back

use_backend premium_back if is_vip and is_api picks the premium backend only when both conditions are true at once. The top-to-bottom ordering means premium requests are always checked first.

Grouping ACLs by Name

Multiple lines with the same ACL name are automatically joined with OR:

Grouping conditions
frontend web_front
    bind *:80
    mode http
 
    acl is_admin hdr(host) -i admin.example.com
    acl is_admin src 10.0.0.0/8
    acl is_admin path_beg /internal
 
    http-request deny deny_status 404 if is_admin path_beg /public
    default_backend web_back

Because is_admin is defined three times with different meanings, that ACL is true if any one of its definitions matches. This is a neat way to combine many possibilities.

Structuring Complex Frontend Logic

Deliberate Evaluation Order

Complex frontend logic must still stay readable by humans. The rules:

  1. Basic validation at the very top: host, method, size.
  2. Security protection: deny for dangerous patterns.
  3. Functional routing: use_backend from the most specific.
  4. A default_backend fallback at the very bottom.
A tidy frontend structure
frontend api_front
    bind *:443 ssl crt /etc/haproxy/certs/fullchain.pem
    mode http
    option httplog
 
    acl has_key req.hdr(X-Api-Key) -m found
    acl is_v1 path_beg /v1
    acl is_v2 path_beg /v2
    acl is_internal src 10.0.0.0/8
 
    http-request deny deny_status 401 if !has_key !is_internal
    http-request deny deny_status 405 if !is_v1 !is_v2
 
    use_backend v2_back if is_v2 has_key
    default_backend v1_back

http-request deny deny_status 405 if !is_v1 !is_v2 rejects paths that aren't v1 or v2 before routing ever happens. This ordering discipline is what separates maintainable configuration from chaos.

Avoiding Common Mistakes

Pitfalls that often appear as ACLs get more complex:

  • Forgetting that rules are evaluated top-down: put the most specific first.
  • Trusting headers without validation: overwrite X-Forwarded-For yourself.
  • Writing regexes without testing: verify path_reg with several real requests.
  • Letting default_backend go missing so unrouted traffic gets rejected.
Quick test of frontend logic
curl -s -o /dev/null -w "%{http_code}\n" \
  -H "X-Api-Key: test" https://localhost/v2/health -k
curl -s -o /dev/null -w "%{http_code}\n" \
  https://localhost/v2/health -k

curl -s -o /dev/null -w "%{http_code}\n" with and without the X-Api-Key header verifies that the deny rules work as expected.

Closing

Episode 16 turns ACLs from simple if-then into a complete logical language: regexes, value conversions, payloads, and condition combinations. With ordering discipline, complex frontends stay maintainable.

Key takeaways:

  • path_reg, req.payload, and value transforms extend ACL expressions.
  • Combine conditions with and, or, and ! in a single decision.
  • ACLs with the same name are joined automatically with OR logic.
  • Structure frontends: validation, security, routing, then fallback.
  • Always provide a default_backend and test the logic with real requests.

In the next episode we'll cover the HAProxy Enterprise features overview — the flagship features of the Enterprise edition, the event-driven architecture and additional modules, and an honest feature set comparison between the Community and Enterprise editions.

Learn HAProxy - Content Switching & ACLs | Learn HAProxy