Http frontend to https Backend on selected paths

I have two incoming requests, one of it needs to go to a “http:// server” and other to “https:// server”.
Below is my acl and backend definitions

------in haproxy_peers.cfg---------
acl downstream_service1 path_beg /downstream_serv1/internal/api
acl downstream_service2 path_beg /downstream_serv2/internal/api

use_backend downstream_serv1_http if downstream_service1
use_backend downstream_serv2_https if downstream_service2
------------------------------------------

backend configs:

--------in backend config file-----------
backend downstream_serv1_http
    http-request set-path "%[path,regsub(^/downstream_serv1/,/)]"
        server  downstream_server1   host-name.domain:port_number check         //*note there is no http/https protocol mentioned.*

backend downstream_serv2_https
    http-request set-path "%[path,regsub(^/downstream_serv2/,/)]"
        server  downstream_server2   host-name2.domain:port_number check      //*note there is no http/https protocol mentioned.*
---------------------------------------------

Expectation is
http://haproxyHost/downstream_serv1/internal/api should be routed to http://host-name.domain:port_number/internal/api

http://haproxyHost/downstream_serv2/internal/api should be routed to https://host-name2.domain:port_number/internal/api

Any help here please?

You didn’t specify what works and what doesn’t work, but at the very least you will have to tell haproxy that serv2 is SSL, which means, adding the ssl keyword and specifying the certification validation method, for example:

ssl verify none

http to http works fine i,e http://haproxyHost/downstream_serv1/internal/api should be routed to http://host-name.domain:port_number/internal/api route works fine. Whereas http to https does not work— gives a 503 service unavailable. Tried below things and these are the outcomes

backend downstream_serv2_https
    http-request set-path "%[path,regsub(^/downstream_serv2/,/)]"
        server  downstream_server2   host-name2.domain:port_number ssl verify none

Health check is ignored for this backend and on firing a http request , it gives 503 service Unavailable
logs look like this
<134>Nov 24 17:54:35 8e0616b2823b apigateway-haproxy[9]: {haproxy,1637776472,503,GET /downstream_serv2/internal/api/**** HTTP/1.1,10.213.210.3,-,-,apigateway,-,srcIP:10.213.210.3,backend:downstream_serv2_https,bIP:xxx.xx.xxx.xxx,bPORT:8443,method:GET,user-agent:-,uri:/downstream_serv2/internal/api/***** }

backend downstream_serv2_https
    http-request set-path "%[path,regsub(^/downstream_serv2/,/)]"
        server  downstream_server2   host-name2.domain:port_number check ssl verify none

health check fails in this case with logs as below:
<133>Nov 24 17:59:18 5c8e0e9ae9cc apigateway-haproxy[8]: Health check for server downstream_serv2_https/downstream_server2 failed, reason: Layer6 invalid response, info: “SSL handshake failure”, check duration: 2ms, status: 0/2 DOWN.
[WARNING] 327/175918 (8) : Health check for server downstream_serv2_https/downstream_server2 failed, reason: Layer6 invalid response, info: “SSL handshake failure”, check duration: 2ms, status: 0/2 DOWN.
<129>Nov 24 17:59:18 5c8e0e9ae9cc apigateway-haproxy[8]: Server downstream_serv2_https/downstream_server2 is DOWN. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.
<128>Nov 24 17:59:18 5c8e0e9ae9cc apigateway-haproxy[8]: backend downstream_serv2_https has no server available!
Server downstream_serv2_https/downstream_server2 is DOWN. 0 active and 0 backup servers left. 0 sessions active, 0 requeued, 0 remaining in queue.

TIA.

First of all, lets try without health checks.

You only have 1 server per backend (unless that is a simplification for the forum), so health checking does not make any sense at all, it’s not like haproxy could failover to a different backend server.

there are more than 1 server per backend(mentioned just 1 to keep it simple).

Yes , tried first without healthchecks, and got a 503

backend downstream_serv2_https
    http-request set-path "%[path,regsub(^/downstream_serv2/,/)]"
        server  downstream_server2   host-name2.domain:port_number ssl verify none

<134>Nov 24 17:54:35 8e0616b2823b apigateway-haproxy[9]: {haproxy,1637776472,503,GET /downstream_serv2/internal/api/**** HTTP/1.1,10.213.210.3,-,-,apigateway,-,srcIP:10.213.210.3,backend:downstream_serv2_https,bIP:xxx.xx.xxx.xxx,bPORT:8443,method:GET,user-agent:-,uri:/downstream_serv2/internal/api/***** }.

this is how frontend cfg looks like

 peers mypeers
     peer haproxy1 0.0.0.0:51024

frontend http_in
    bind :7080

    #capturing 'client_id' from the request
    stick on req.hdr(client_id)
    http-request capture req.hdr(client_id) len 100
    http-request capture req.hdr(X-Unique-Id) len 100
/* some logic for rete-limiting*/

acl downstream_service1 path_beg /downstream_serv1/internal/api
acl downstream_service2 path_beg /downstream_serv2/internal/api

use_backend downstream_serv1_http if downstream_service1
use_backend downstream_serv2_https if downstream_service2

Maybe you backend server rejects all HTTPS connections without proper SNI, try setting it to the hostname from the backend server certificate like this:

sni str(www.example.org) check-sni www.example.org

We do not have any SNI configured as such at our backend server. Need to check if it is set by default. Is this something that needs to be set at both app server and HAProxy backend server config?
We do not have mode set to tcp anywhere, is it required?

If you backend requires SNI, then haproxy needs to send it, for both health checks and client traffic.

I don’t know anything about your app server, I certainly can’t tell you what it’s defaults are.

No, tcp mode is unrelated to the problem at hand.

I tried this out with a basic haproxy config file without docker container on version 1.8 and it works fine. Have trouble when running this in docker container with version 2.2.4 , 2.5 and 2.6 (image details: haproxytech/haproxy-ubuntu 2.6 a78e863f2eb3). Routing to backend server app2 works fine with and without container . Same config file with backend server app1 gives a 503.

    global
  stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
  log stdout local0 info

defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
    log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
#{"haproxy",%Ts,%ST,"%r","%ci"}

#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend  main
   bind :7080
   default_backend             app

#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
    balance     roundrobin
    server staticApp some_ip:8443 ssl verify none

#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
    balance     roundrobin
#    server app2 some_ip:11002 check
    server  app1 some_ip:8443 ssl verify none

Do you see what I am missing here? Kindly help