HAProxy config tutorials
HTTP rewrites
Use the http-request
and http-response
configuration directives to rewrite HTTP requests and responses. You can place them into a frontend
or backend
section.
Rewrite requests Jump to heading
Use the http-request
configuration directives to rewrite HTTP requests. You can place them into a frontend
or backend
section. Use them to rewrite requests sent from clients before the load balancer forwards them to a backend server. The server will see something different than what the client sent.
Change the HTTP request method Jump to heading
Use http-request set-method
to change the method (e.g. GET, POST, PUT) on a request before relaying it to a backend server. In the example below, we change GET requests made to the /login
URL path to be POST requests:
haproxy
frontend wwwbind :80acl url_login path_beg -i /loginhttp-request set-method POST if METH_GET url_loginuse_backend webservers
haproxy
frontend wwwbind :80acl url_login path_beg -i /loginhttp-request set-method POST if METH_GET url_loginuse_backend webservers
As another example, turn a GET into a POST if there is data in the body of the request by checking the Content-Length
header:
haproxy
frontend wwwbind :80acl body_has_data req.hdr_val(Content-Length) gt 0http-request set-method POST if METH_GET body_has_datause_backend webservers
haproxy
frontend wwwbind :80acl body_has_data req.hdr_val(Content-Length) gt 0http-request set-method POST if METH_GET body_has_datause_backend webservers
Add a header Jump to heading
Use http-request add-header
to add a new HTTP header to a request before relaying it to a backend server. In the example below, we add an X-Forwarded-For
header containing the client IP address:
haproxy
frontend wwwbind :80http-request add-header X-Forwarded-For %[src]use_backend webservers
haproxy
frontend wwwbind :80http-request add-header X-Forwarded-For %[src]use_backend webservers
Going further, you can add a condition that first checks whether the X-Forwarded-For
header exists and only add it if it does not:
haproxy
frontend wwwbind :80acl h_xff_exists req.hdr(X-Forwarded-For) -m foundhttp-request add-header X-Forwarded-For %[src] unless h_xff_existsuse_backend webservers
haproxy
frontend wwwbind :80acl h_xff_exists req.hdr(X-Forwarded-For) -m foundhttp-request add-header X-Forwarded-For %[src] unless h_xff_existsuse_backend webservers
Set a header Jump to heading
Use http-request set-header
to add a new header or overwrite it if it already exists. In the example below, we overwrite any existing X-Forwarded-For
header with one containing the client’s IP address by referencing the src
fetch method:
haproxy
frontend wwwbind :80http-request set-header X-Forwarded-For %[src]use_backend webservers
haproxy
frontend wwwbind :80http-request set-header X-Forwarded-For %[src]use_backend webservers
In the next example, we change the Host
header when traffic is sent to the maintenance
backend:
haproxy
backend maintenancehttp-request set-header Host maintenance.domain.com# server lines...
haproxy
backend maintenancehttp-request set-header Host maintenance.domain.com# server lines...
Delete a header Jump to heading
Use http-request del-header
to remove an HTTP header from a request before relaying it to a backend server. In the example below, we delete any existing X-Forwarded-For
header:
haproxy
frontend wwwbind :80http-request del-header X-Forwarded-Foruse_backend webservers
haproxy
frontend wwwbind :80http-request del-header X-Forwarded-Foruse_backend webservers
In the next example, we delete all Cookie
headers before sending the request to the backend servers, which in this case is a pool of cache (Varnish) servers:
haproxy
backend b_cachesacl at_least_one_cookie req.cook_cnt() gt 0http-request del-header Cookie if at_least_one_cookie# server lines...
haproxy
backend b_cachesacl at_least_one_cookie req.cook_cnt() gt 0http-request del-header Cookie if at_least_one_cookie# server lines...
Replace a header by using a regular expression Jump to heading
Use http-request replace-header
to capture the entire value of a header by using a regular expression and then replace that value with a new one. You can use this technique to add data to a header, as in the example below, where we add a new IP address to the X-Forwarded-For
header before relaying it to a backend server:
haproxy
frontend wwwbind :80acl h_xff_exists req.hdr(X-Forwarded-For) -m foundhttp-request replace-header X-Forwarded-For (.*) %[src],\1 if h_xff_existsuse_backend webservers
haproxy
frontend wwwbind :80acl h_xff_exists req.hdr(X-Forwarded-For) -m foundhttp-request replace-header X-Forwarded-For (.*) %[src],\1 if h_xff_existsuse_backend webservers
We use a regular expression capture group to capture the whole, existing value. Then, we add the new IP address to the beginning. We get the IP address with the src
fetch method. This updates the string below…
text
X-Forwarded-For: 192.168.100.1, 10.0.0.2
text
X-Forwarded-For: 192.168.100.1, 10.0.0.2
…to become this one (considering the client’s IP is 172.16.0.2):
text
X-Forwarded-For: 172.16.0.2, 192.168.100.1, 10.0.0.2
text
X-Forwarded-For: 172.16.0.2, 192.168.100.1, 10.0.0.2
Replace part of a header by using a regular expression Jump to heading
Use http-request replace-value
to capture part of a header’s value by using a regular expression and then replace that part with a new one. In the example below, we capture the Host
header’s value up to the first colon. We then strip off the colon and port, if any:
haproxy
frontend wwwbind :80http-request replace-value Host (.*):.* \1use_backend webservers
haproxy
frontend wwwbind :80http-request replace-value Host (.*):.* \1use_backend webservers
This updates the string below…
text
Host: www.domain.com:80, static.domain.com:8080
text
Host: www.domain.com:80, static.domain.com:8080
…into the following one:
text
Host: www.domain.com, static.domain.com
text
Host: www.domain.com, static.domain.com
In cases where a header has multiple values, they are expected to be separated by a comma. The load balancer looks for commas and applies the replacement to each value it finds.
Set the URL path Jump to heading
Use http-request set-path
to change the requested URL path before relaying it to a backend server. Below, we change the URL path for JPG images so that it begins with /images/
, but only if not already set:
haproxy
frontend wwwbind :80acl p_ext_jpg path_end -i .jpgacl p_folder_images path_beg -i /images/http-request set-path /images/%[path] if !p_folder_images p_ext_jpguse_backend webservers
haproxy
frontend wwwbind :80acl p_ext_jpg path_end -i .jpgacl p_folder_images path_beg -i /images/http-request set-path /images/%[path] if !p_folder_images p_ext_jpguse_backend webservers
This changes the requests below…
text
GET /images/flower.jpg HTTP/1.1GET /daisy.jpg HTTP/1.1
text
GET /images/flower.jpg HTTP/1.1GET /daisy.jpg HTTP/1.1
…into the following ones, respectively:
text
GET /images/flower.jpg HTTP/1.1GET /images/daisy.jpg HTTP/1.1
text
GET /images/flower.jpg HTTP/1.1GET /images/daisy.jpg HTTP/1.1
Set the query string Jump to heading
Use http-request set-query
to change the requested URL’s query string. You can use the query
fetch method to get the current query string value. Then use the regsub
function to replace the first occurrence of a given substring. In the example below, we replace the string %3D
with =
in the query string. The third parameter is set to g
, which applies the replacement to all occurrences within the string:
haproxy
frontend wwwbind :80http-request set-query %[query,regsub(%3D,=,g)]use_backend webservers
haproxy
frontend wwwbind :80http-request set-query %[query,regsub(%3D,=,g)]use_backend webservers
You can also use the urlp
fetch method to get one of the query string’s parameters. Below, we reorder the parameters in the query string to ensure that the user
parameter comes before the group
parameter:
haproxy
frontend wwwbind :80http-request set-query user=%[urlp(user)]&group=%[urlp(group)]use_backend webservers
haproxy
frontend wwwbind :80http-request set-query user=%[urlp(user)]&group=%[urlp(group)]use_backend webservers
This changes the request below…
text
GET /test.php?group=admin&user=foo HTTP/1.1
text
GET /test.php?group=admin&user=foo HTTP/1.1
…into the following one:
text
GET /test.php?user=foo&group=admin HTTP/1.1
text
GET /test.php?user=foo&group=admin HTTP/1.1
Set the URI Jump to heading
Use http-request set-uri
to rewrite the entire URI string of an HTTP request, including its HTTP scheme, authority, path, and query string. In the example below, we create one URL for HTTP and another for HTTPS when forwarding traffic to a proxy server:
haproxy
backend b_squidacl https ssl_fchttp-request set-uri https://%[req.hdr(Host)]%[path]?%[query] if httpshttp-request set-uri http://%[req.hdr(Host)]%[path]?%[query] unless https# servers list...
haproxy
backend b_squidacl https ssl_fchttp-request set-uri https://%[req.hdr(Host)]%[path]?%[query] if httpshttp-request set-uri http://%[req.hdr(Host)]%[path]?%[query] unless https# servers list...
This changes the request below…
text
GET /test.php?group=admin&user=foo HTTP/1.1Host: www.domain.com
text
GET /test.php?group=admin&user=foo HTTP/1.1Host: www.domain.com
…into this one if the user connected over HTTP:
text
GET http://www.domain.com/test.php?group=admin&user=foo HTTP/1.1
text
GET http://www.domain.com/test.php?group=admin&user=foo HTTP/1.1
…or into this one if the user connected over HTTPS:
text
GET https://www.domain.com/test.php?group=admin&user=foo HTTP/1.1
text
GET https://www.domain.com/test.php?group=admin&user=foo HTTP/1.1
Rewriting anywhere in the request using regexes Jump to heading
Deprecated feature
This feature was removed in:
- HAProxy 1.9
- HAProxy Enterprise 1.9r1
- HAProxy ALOHA 11.0
The legacy statements reqrep
and reqirep
are still useful in cases not yet covered by the http-request
directives.
reqrep
applies a regex to each line of the request buffer in a case-sensitive manner.reqirep
is case insensitive.
text
reqrep <search> <replace> [<cond>] reqirep <search> <replace> [<cond>]reqirep <search> <replace> [<cond>] reqirep <search> <replace> [<cond>]
text
reqrep <search> <replace> [<cond>] reqirep <search> <replace> [<cond>]reqirep <search> <replace> [<cond>] reqirep <search> <replace> [<cond>]
This directive needs a regular expression to <search>
the content to replace, a regular expression <replace>
to apply the modification , and an optional <condition>
to apply to this rule.
This feature uses PCRE compatible regular expressions.
Below, we replace /jpg/
with /images/
in the URL path:
haproxy
frontend wwwbind :80reqrep ^([^ ]*) /jpg/(.*) 1 /images/2use_backend webservers
haproxy
frontend wwwbind :80reqrep ^([^ ]*) /jpg/(.*) 1 /images/2use_backend webservers
Next, we rewrite the Host
header from static.domain.com
to www.domain.com
:
haproxy
frontend wwwbind :80acl h_static hdr(Host) -m beg static.domain.comreqirep ^Host: static.domain.com Host: www.domain.com if h_staticuse_backend webservers
haproxy
frontend wwwbind :80acl h_static hdr(Host) -m beg static.domain.comreqirep ^Host: static.domain.com Host: www.domain.com if h_staticuse_backend webservers
Rewrite responses Jump to heading
Use the http-response
configuration directives to rewrite HTTP responses before they are sent back to clients. You can place them into a frontend
or backend
section. The client will see something different than what the server sees.
Add a header Jump to heading
Use http-response add-header
to add a header to the response before relaying it back to the client. In the example below, we add an X-Via
header containing the hostname of the current load balancer server processing the traffic:
haproxy
frontend wwwbind :80http-response add-header X-Via %[env(HOSTNAME)]use_backend webservers
haproxy
frontend wwwbind :80http-response add-header X-Via %[env(HOSTNAME)]use_backend webservers
Set a header Jump to heading
Use http-response set-header
to change the current value of a header. In the example below, we give the Server
header the value webserver
, which can be useful for hiding the true name of the server:
haproxy
frontend wwwbind :80http-response set-header Server webserveruse_backend webservers
haproxy
frontend wwwbind :80http-response set-header Server webserveruse_backend webservers
Delete a header Jump to heading
Use http-response del-header
to remove a header. Below, we delete several headers that are set by Varnish:
haproxy
backend b_statichttp-response del-header X-Varnishhttp-response del-header X-Varnish-Cachehttp-response del-header X-Varnish-Serverhttp-response del-header X-Cache# servers list...
haproxy
backend b_statichttp-response del-header X-Varnishhttp-response del-header X-Varnish-Cachehttp-response del-header X-Varnish-Serverhttp-response del-header X-Cache# servers list...
Replace a header by using a regular expression Jump to heading
Use http-response replace-header
to change a header by using a regular expression. Below, we update the Cookie
header named JSESSIONID
, which was set by the server, with the Secure
flag if the client-side connection is ciphered:
haproxy
frontend wwwbind :80acl https ssl_fcacl secured_cookie res.cook(JSESSIONID),lower -m sub securehttp-response replace-header Set-Cookie (.*) "\1; Secure" if https !secured_cookieuse_backend webservers
haproxy
frontend wwwbind :80acl https ssl_fcacl secured_cookie res.cook(JSESSIONID),lower -m sub securehttp-response replace-header Set-Cookie (.*) "\1; Secure" if https !secured_cookieuse_backend webservers
We use a regular expression capture group to capture the whole, existing value. Then, we add the new flag to the end, after a semi-colon. This assumes that the server sets up a single cookie. HTTP RFC specifies that the comma ,
character is a header field delimiter.
Replace part of a header by using a regular expression Jump to heading
Use http-response replace-value
to capture part of a header’s value by using a regular expression and then replace that part with a new one. In the example below, we insert a Secure
flag on each cookie set up by the server:
haproxy
frontend wwwbind :80http-response replace-value Set-Cookie (.*) \1;\ Secureuse_backend webservers
haproxy
frontend wwwbind :80http-response replace-value Set-Cookie (.*) \1;\ Secureuse_backend webservers
In cases where a header has multiple values, they are expected to be separated by a comma. The load balancer looks for commas and applies the replacement to each value it finds.
See also Jump to heading
- http-request add-header
- http-request del-header
- http-request replace-header
- http-request replace-value
- http-request set-header
- http-request set-method
- http-request set-path
- http-request set-query
- http-request set-uri
- http-response add-header
- http-response del-header
- http-response replace-header
- http-response replace-value
- http-response set-header
Do you have any suggestions on how we can improve the content of this page?