pass a backend from backend map to haproxy nbsrv - haproxy

Can someone advise what I have to change in the nbsrv expression in order to make it work:
frontend webfarm
bind 11.22.33.44:80
...
acl MAIN_not_enough_capacity nbsrv([%[req.hdr(host),lower,map(/etc/haproxy/backend.map,bk_default)]]) eq 0
http-request redirect code 301 location http://global-swajm.example.com if MAIN_not_enough_capacity
use_backend %[req.hdr(host),lower,map(/etc/haproxy/backend.map,bk_default)]
The idea is according to the host in the header to get the right backend name from the map file.
If there are no available servers in this backend the request will be redirected to another haproxy (in another DC).
use_backend is working perfectly:
use_backend %[req.hdr(host),lower,map(/etc/haproxy/backend.map,bk_default)]
but I don't know how to modify the expression for nbsrv in order to pass the backend name:
nbsrv([%[req.hdr(host),lower,map(/etc/haproxy/backend.map,bk_default)]])

just chiming in after having struggled with the same
Use
acl MAIN_not_enough_capacity req.hdr(host),lower,map(/etc/haproxy/backend.map,bk_default),nbsrv eq 0
instead

Related

How to pass path from haproxy frontend to backend in version 1.5.18

I have a condition where I need to pass whatever path is given in the frontend url to a backend redirect statement. E.g. Frontend https://example.com/abc/xyz to backend http://server-address:port/abc/xyz. I am using http redirect in the backend as of now. But now it has been requested to pass any path along with the frontend URL, to be appended to backend as well. I cannot use redirect on frontend as I need to use port 443 which is being used by other service. So I am use acl_path to point to a different backend, so I need to achieve this using backend itself. My frontend config is below-
frontend a
bind 10.10.10.10:443 ssl crt /etc/pki/org/key/somekey.key force-tlsv12 ciphers SOME-CIPHER
mode http
acl a_dev_app hdr_dom(host) -m beg a.dev.app.
acl b_dev_app hdr_dom(host) -m beg b.dev.app.
option http-server-close
use_backend a if a_dev_app
use_backend b if b_dev_app
Backend config-
backend b
balance roundrobin
cookie a-web-backend insert indirect nocache
http-request redirect location http://server-url:8081/b
mode http
option httpchk /b
server a-web-d01 http://server-url:8081 check maxconn 150 cookie a-web-d01

How to remove query string with reqrep in Haproxy backend?

I am trying to write a reqrep query to try and strip out a query string. I am using ACLs with urlp_end to direct to the correct backend, but the query string that is being used for that is being passed over to the backend.
The frontend uses an ACL like this:
acl Test_ACL urlp_end(device) -m str eq 14110
use_backend Device_1 if Test_ACL
In my backend I just have the server IP, but i would like to remove the device parameter in the backend. Here is an example:
https://example.com/chkimg/FRONT200GRAY8_1.JPG?device=14110
This forwards to the right backend. Basically all i want to do is in the backend traffic, strip the "?device=______" parameter from the URL, so that it just forwards this to the backend, with the entire device parameter invisible to the backend server:
https://example.com/chkimg/FRONT200GRAY8_1.JPG
Member on Haproxy forum answered this for me
http-request set-uri %[path]

HAProxy - Add Trailing Slash

I am working on a project where I need requests destined to a particular page to be routed to a separate backend.
For example, all requests for https://mycooldomain.com will go to backend "A". But, if navigating to https://mycooldomain.com/secretpage I want it to go to backend "B".
Now, I have this working but running into an issue where I need the trailing slash for this to work correctly.
So, I need a way to say if request is https://[whateverhostnameisused]/secretpage redirect to https://[whateverhostnameisused]/secretpage/.
Here is a sample of my config so far:
frontend f_https
bind *:443 ssl crt cert.pem
reqadd X-Forwarded-Proto:\ https
#define hosts
acl host_a hdr(host) -i a.mycooldomain.com
acl host_b hdr(host) -i b.mycooldomain.com
acl host_c hdr(host) -i c.mycooldomain.com
#custom acls
acl secret path_beg -i /secretpage
#Custom redirects
##define backend
use_backend b_secret if secret
use_backend b_a if host_a
use_backend b_b if host_b
use_backend b_c if host_c
default_backend b_https
backend b_secret
server secret 192.168.15.15:5575 check
It seems that you are looking for something like this:
http-request redirect scheme https drop-query append-slash if { path -m str /secretpage }
This should work if applied to either the frontend or the backend.
http://cbonte.github.io/haproxy-dconv/1.6/configuration.html#4.2-redirect%20scheme
Specifying the scheme is only necessary because the syntax requires one of location | prefix | scheme, and with the other two options, you have to reassemble the URL yourself in the config.
Note also that reqadd is not officially deprecated, but the preferred way to add that request header is like this:
http-request set-header X-Forwarded-Proto https
Note that no : is specified and the space after the header name must not be escaped with \. This accomplishes the same result, but it uses a different code path inside HAProxy, and should be a more efficient operation. You will want to use the the http-request and http-response directives instead of reqxxx and rspxxx where possible, as they are also better suited to more complex manipulations.

HAProxy path_beg not redirecting

I'm testing a simple haproxy rule to make http://localhost/haproxy-dconv take me to http://cbonte.github.io/haproxy-dconv but it isn't working. 404 response seems to be from the site but the path isn't resolving.
frontend HTTP
mode http
bind *:80
acl url_dconv path_beg /haproxy-dconv
use_backend dconv-backend if url_dconv
backend dconv-backend
mode http
server dconv cbonte.github.io
Try this -
frontend HTTP
mode http
bind *:80
use_backend dconv-backend if { path_beg /haproxy-dconv/ }
backend dconv-backend
mode http
server dconv cbonte.github.io
Source: https://cbonte.github.io/haproxy-dconv/1.7/configuration.html#use_backend
That is because the Host header that is being sent is localhost, instead of cbonte.github.io. Add this to your backend:
http-request set-header Host cbonte.github.io
Also note that without the ending slash, you will get a 301, so make sure you send http://localhost/cbonte-dconv/ and fix your ACL.
You are using Haproxy in an incorrect way.
You need to match the ACL to get the URL between host and query parameter as you do:
acl url_dconv path_beg /haproxy-dconv
Then using this ACL to redirect from localhost if ACL is matched:
redirect prefix http://cbonte.github.io code 301 if url_dconv
But again this is more a conceptual problem of thinking redirect and matching path.

HAproxy domain name to backend mapping for path(url) based routing

Does HAProxy support domain name to backend mapping for path based routing.
Currently it does support maps for vhost:
frontend xyz
<other_lines>
use_backend backend1 if { hdr(Host) -i myapp.domain1.com }
use_backend backend2 if { hdr(Host) -i myapp.domain2.com }
Can be rewritten using maps as:
frontend xyz
<other_lines>
use_backend %[req.hdr(host),lower,map_dom(/path/to/map,default)]
With the contents of map file as:
#domainname backendname
myapp.domain1.com backend1
myapp.domain2.com backend2
But if the routing is based on paths as shown in the example below:
frontend xyz
acl host_server_myapp hdr(host) -i myapp.domain.com
acl path_path1 path_beg /path1
acl path_path2 path_beg /path2
use_backend backend1 if host_server_myapp path_path1
use_backend backend2 if host_server_myapp path_path2
Is it possible to have mapping for this usecase? Using base instead of hdr(host) might give the entire path but it will not have the flexibility of domains since base is string comparison. Is there an other way to convert this to haproxy maps.
Start with the Layer 7 base fetch --
This returns the concatenation of the first Host header and the path part of
the request, which starts at the first slash and ends before the question
mark.
...then use map_beg() to match the beginning of the string to the map.
use_backend %[base,map_beg(/etc/haproxy/testmap.map,default)]
If the map file /etc/haproxy/testmap.map has a line matching the prefix, the backend in the map file is used. Otherwise, the backend called default will be used (that's the 2nd argument to map_beg() -- the value to be returned if the map doesn't match).
If the resulting backend doesn't actually exist, HAProxy continues processing the request as if this statement weren't configured at all.
So your map file would look something like this:
example.com/foo this-backend # note, also matches /foo/ba
example.com/foo/bar that-backend # note, matches /foo/bar
example.org/foo some-other-backend
To treat a subdomain as equivalent to the parent domain (e.g., treating example.com and www.example.com to be handled equivalently, without map duplication, as discussed in comments) the regsub() converter could be used to modify the value passed to the map:
use_backend %[base,regsub(^www\.,,i),map_beg(/etc/haproxy/testmap.map,default)]