testing acl in backend haproxy - haproxy

I want to test if path of URL is created (or diponible) in server (1 or 2) , before using backend.
now i'm using that :
use_backend apps if {path_beg -i /test/}
but what i want is :
use_backend apps if {path_beg -i {variable_path}} else use_backend apps2
someone can give some help

Related

Backend routing based on cookie name substring

Example cookie name in request:
wordpress_logged_in_8df6736080e8...
I want to create an haproxy acl based on when the cookie name begins with wordpress_logged_in and then route the logged in users based on that acl to separate backend.
acl url_admin path_beg -i /wp-admin /wp-login.php
acl url_admin hdr_sub(cookie) wordpress_logged_in
This config is working for me, as it matches the whole cookie header and some URLs. Without the first ACL it's not working.
You can try to use cook_beg for the acl
acl cookie_backend cook_beg(wordpress_logged_in) -m found
...
use_backend cookie_backend if cookie_backend
...
default_backend default_backend
This Blog post explains the haproy acl Introduction to HAProxy ACLs
In the doc can you find more details Using ACLs to form conditions

Haproxy acl - service unavailable

I'm trying to setup haproxy acl, and it gives me 503: Service unavailable error, even redirect by port works fine. What am I doing wrong?
Appreciate any help.
This doesn't work by x.x.x.x/havana :
frontend https
bind *:80
mode http
option httpclose
acl otter-path path -i /havana/
use_backend otter-server if otter-path
This shows backend fine by x.x.x.x:82 :
frontend otter-server
bind *:82
option forwardfor
default_backend otter-server
Backend configuration:
backend otter-server
server otter2 192.168.0.15:8004
acl otter-path path -i /havana/
remove the last "/" i.e:
acl otter-path path -i /havana
your trying to hitx.x.x.x/havana but matching x.x.x.x/havana/
the problem was - it redirects not to backend, but to backend/havana, which doesn't exist.
Solution is to remove subpath after redirect, so it points exact to backend root
backend annotrack-mouse
balance roundrobin
http-request set-uri %[url,regsub(^/havana/mouse,/,)] if { path_beg /ha$
server annotrack-mouse 192.168.0.10:3000
option httpchk

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 - Serving a URL from 2nd machine if the 1st returns a 404

I have a situation where I have part of a website (certain URL paths) being served from one backend server while all other URLs are being served from a different default backend in HAProxy.
Now, because of the way the application logic was written, the files to be served under the same URL path could be created at the same path on either of the two physical server machines. I would like to be able to serve these files regardless of which machine the file exists on. So in a nutshell, how can I forward the request to one backend and if the response is a 404 (the file does not exist there), forward the request to be served from the other backend?
I am a complete noob to HAProxy so any help will be appreciated. Thanks.
The relevant portions of my haproxy.conf:
frontend frontend0
...
acl de path_beg /path1
acl de path_beg /path2
acl de path_beg /path3
use backend backend1 if de
default_backend bakend
backend backend1
...
server server_name 127.0.0.1:8000
backend backend2
...
server server_name 192.168.11.1:8000
There is a path /path4 that needs to be served from both of these machines depending on where the file exists.
Thanks to #Michael-sqlbot for the hint and this question on ServerFault for the outline of the answer. The setup I finally ended up using is as follows:
I setup a separate URL /_path4 that is served from one backend while the original URL /path4 is served from the other backend.
On receiving a 404 response from the first backend for /path4, I redirect to the URL /_path4
My configuration file now looks as follows:
frontend frontend0
...
acl de path_beg /path1
acl de path_beg /path2
acl de path_beg /path3
acl de path_beg /_path4
use_backend backend2 if de
default_backend backend1
...
backend backend1
...
http-request set-var(txn.path) path
server server_name 127.0.0.1:8000
http-response redirect location %[var(txn.path),regsub('^/path4','/_path4')] code 303 if { status 404 } { var(txn.path) -m beg '/path4' }
...
backend backend2
...
server server_name 192.168.11.1:8000
As explained in #Michael-sqlbot's excellent comments to the linked question, the setting of a transaction variable is required because at the http-response stage, the buffer has been released and so the normal path variable used in the frontend is not available.

pass a backend from backend map to haproxy nbsrv

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