Hmm, so 503 is also returned by haproxy if no server is available to service a request (example for a backend with no servers or if the server is not available failing the health check). As I recall, we did the error page on a request as it gives the ability to override it in a custom template.
Now that said, if the app (server associated with a haproxy backend) is returning 503s, that content should get passed back as is. Meaning you should see your custom error page being returned back to the server.
and it returns the content + status code back to the requester.
If that's not the case - from what you are seeing, it is more than likely that haproxy has marked the backend server down as unavailable - which means its failing health checks.
Is your server always returning 503 - example for a GET/HEAD on / ? That could cause haproxy to mark it as down.
You can also see the stats in haproxy to look at if the server has been marked down:
cmd="echo 'show stat' | socat unix-connect:/var/lib/haproxy/run/haproxy.sock stdio"
echo "$cmd" | oc rsh <router-pod-name> # replace with router pod name.