Marathon-lb rules for different paths - haproxy

My marathon-lb configuration:
"labels": {
"HAPROXY_GROUP": "external",
"HAPROXY_0_VHOST": "test.com",
"HAPROXY_0_MODE": "http"
}
I want it route only requests like test.com/12345 to internal endpoint
/results?q=123. How to achieve that?
P.S. Nginx rule for the same purpose looks like:
location ~* /[\w\-]+?$ {
proxy_pass http://127.0.0.1:8094;
rewrite ^/([\w\-]+?)$ //results?q=$1? break;
}

As you probably know marathon-lb is HAProxy plus some wrappers. You can add a redirect to HAProxy configuration, by using HAPROXY_0_BACKEND_HTTP_OPTIONS label. There's a legacy reqrep statement which you may find convenient and you can also go for 301 redirect. For example you can do:
"HAPROXY_0_BACKEND_HTTP_OPTIONS": " reqrep ^/([\w\-]+?)$ /results?q=\\1 \n",
or
"HAPROXY_0_BACKEND_HTTP_OPTIONS": " acl is_foo path -i /foo \n redirect code 301 location /bar if is_foo\n",
Note double spaces for indent. Not that you'll have to play with escapes to make it work.

Related

HAProxy: hdr_dom(host) with redirects

We have a couple of haproxy configurations running fine for the most part.
In our scenario, we simply route requests based on domain names.
Here a sample for one domain, drawmessage.com:
frontend http
bind *:80
redirect prefix http://app.drawmessage.com code 301 if { hdr_dom(host) -i www.app.drawmessage.com }
redirect prefix http://drawmessage.com code 301 if { hdr_dom(host) -i www.drawmessage.com }
redirect prefix https://drawmessage.com code 301 if { hdr_dom(host) -i drawmessage.com }
use_backend http:app.drawmessage.com if { hdr_dom(host) -i app.drawmessage.com }
use_backend http:app.drawmessage.com if { hdr_dom(host) -i app-drawmessage-com.d250.hu }
use_backend http:drawmessage.com if { hdr_dom(host) -i drawmessage.com }
use_backend http:drawmessage.com if { hdr_dom(host) -i drawmessage-com.d250.hu }
There are other domains also, this is filtered for this domain only. As you can see, after redirects for www, we apply a special redirect for drawmessage.com, but theoretically not for app.drawmessage.com.
frontend https
bind *:443 ssl crt /var/haproxy
redirect prefix https://app.drawmessage.com code 301 if { hdr_dom(host) -i www.app.drawmessage.com }
redirect prefix https://drawmessage.com code 301 if { hdr_dom(host) -i www.drawmessage.com }
use_backend https:app.drawmessage.com if { hdr_dom(host) -i app.drawmessage.com }
use_backend https:app.drawmessage.com if { hdr_dom(host) -i app-drawmessage-com.d250.hu }
use_backend https:drawmessage.com if { hdr_dom(host) -i drawmessage.com }
use_backend https:drawmessage.com if { hdr_dom(host) -i drawmessage-com.d250.hu }
The problem is that actually, we do not want a redirect to https for the subdomain app.drawmessage.com, but since we have a redirect for the domain the redirect rule applies for both. Reordering the rules in a way, so that the sorting matches the configuration we want to achieve does produce the same result, and we get haproxy warnings:
a 'redirect' rule placed after a 'use_backend' rule will still be processed before.
If the order of configuration lines affects the order of processing a request, thus the ordering is a configuration parameter itself, why are redirect rules processed before use_backend rules? ...
Anyone has a suggestion how to achieve domain-based routing, with the correct preference of redirects? I would prefer a clean and simple way, ..
Don't use hdr_dom(). Just use hdr().
redirect prefix https://drawmessage.com code 301 if { hdr(host) -i drawmessage.com }
The _dom suffix means you want to match the value given later against any number of complete, consecutive domain-name-like tokens found in the specified header, so the pattern you provide must begin either at the beginning of the string or immediately following a . and must end either at the end of the string or be immediately followed by a .. That isn't what you want to do, so hdr_dom() isn't the correct fetch to use.
The notation may imply that you are comparing left value against right value, but the comparison is actually right value against left value.
a 'redirect' rule placed after a 'use_backend' rule will still be processed before because these directives are handled by different parts of the HAProxy code, at different stages of request processing. Within each class of rule, the order is preserved, but redirects are handled near the beginning and backend selection is near the end of request processing.

Redirect/rewrite nginx location to .sock file without prefix

I have one server that has several APIs running on it. One of them is users-DB The following gets down to gunicorn just fine:
location /usersDB/ {
include proxy_params;
proxy_pass http://unix:/home/ubuntu/projects/UsersDB-api/app.sock;
}
Except when I try to access the usersDB API's /helloWorld route, and look in the logs at gunicorn.err I see:
GET /usersDB/helloWorld
I was hoping to see:
GET /helloWorld
Of course, gunicorn returns 404s and that is what I see in my browser. I've tried rewrite rules:
location /usersDB/ {
rewrite /usersDB/(.*) /$1 last;
include proxy_params;
proxy_pass http://unix:/home/ubuntu/projects/UsersDB-api/app.sock;
}
But the above results in the requests making their way to /var/www/htmlhelloWorld instead of app.sock.
I know that if you use a url for the proxy_pass you just add a trailing /, but I'm not sure what to do in the case of a sock file.
How do I get rid of the /usersDB/ suffix that is now included on all routes in nginx?
Use a separating :. For example:
proxy_pass http://unix:/home/ubuntu/projects/UsersDB-api/app.sock:/;
See this document for details.

Nginx redirect without scheme and hostname

I have used return or rewrite in Nginx to redirect, but both will redirect with the http header Location which has value of the full url, but I want it just value the path.
for example:
return 301 /test;
or
rewrite ^/$ /test permanent;
will has the Location value of
http://www.example.com/test
but I want it be just
/test
I wonder if it is possible.
Solved.
as of 1.11.8, just set the directive(Thanks to #RichardSmith):
absolute_redirect off;
before 1.11.8, I find a wonderful answer(Thanks to #xiaochen):
https://stackoverflow.com/a/39462409

Nginx redirect http to https and remove trailing slashes with one single redirect

I want to redirect http to https and remove trailing slashes in nginx with one single redirect. The solution I have today is the following:
server {
listen 80;
server_name www.example.com
rewrite ^/(.*)/$ /$1 permanent;
return 301 https://$host$request_uri;
}
The problem with this solution is that it will give two redirects
Gives Two redirects:
http://www.example.com/test/ --> http://www.example.com/test
http://www.example.com/test --> https://www.example.com/test
Is it possible to make a solution where you only get one single redirect like bellow?
http://www.example.com/test/ --> https://www.example.com/test
when I looked through the documentation of nginx rewrite and return methods I felt like it should be possible to do it with a single rewrite somehow:
rewrite ^/(.*)/$ https://$host$request_uri permanent;
But nothing I have tried have given me the correct results.
You already had the components of a correct solution. Use the scheme and hostname, together with the capture to construct the destination URL:
rewrite ^/(.*)/$ https://$host/$1 permanent;

with nginx, how to redirect part of request to apache

Some solutions about redirection can be found. But what I want to do is redirecting part of requests to another server, specifically, only when a request url includes string "service". For example:
http://localhost/service/image-------------> http://localhost:8080/service/image
http://localhost/service/image/upload------> http://localhost:8080/service/image/upload
http://localhost/service/blog--------------> http://localhost:8080/service/blog
.....
.................................................................................................................................................................
but blow will still served by ngnix,cause no "service" included within url
http://localhost/wiki/....
http://localhost/video/....
How to do this?
You need to use location regex matching together with proxy_pass, example:
upstream apache {
server 127.0.0.1:8080;
}
# in your server block:
server{
# location matching is prioritized by accuracy and order of definition
location ~* ^/service {
proxy_pass http://apache;
proxy_redirect off;
}
}
^/service will match any request beginning with /service and forward it to Apache.
proxy_pass is transparent for the user, i.e. it will forward the request to Apache and return the output to the user.
For more info on location matching, checkout http://wiki.nginx.org/HttpCoreModule#location
If I understood you correctly:
location / {
if ($request_uri ~* "^/service/.*") {
rewrite ^ http://localhost:8080$request_uri permanent;
}
}
P.S. did not check