Nginx reverse proxying to HTTPS upstream getting 502 Bad Gateway

nginxreverse-proxyssl

My goal is to write Jasmine (a JavaScript BDD testing framework) tests that exercise a back-end API built by a separate team.

I have a Jasmine server running on port 9000. That code issues AJAX requests with a relative path that begin with /web/. I want those requests to be directed to the backend.

So far, I've got a reverse proxy to an upstream block like so:

upstream backend {
  server api-dev.example.com;
}

server {
  ...

  location / {
    proxy_pass http://localhost:9000;
    ...
  }

  location /web/ {
    proxy_pass https://backend/web/;
    ...
  }
}

Traffic to '/' is working fine, but the AJAX requests (for example, to

http://localhost:50000/web/internal?action=network-statistics

) are 502'ing. I believe it's hitting the correct endpoint but there's an SSL error. Nginx's error log seem to confirm my suspicion:

2013/12/13 16:55:28 [error] 1885#0: *257 SSL_do_handshake() failed (SSL: error:140770FC:SSL routines:SSL23_GET_SERVER_HELLO:unknown protocol) while SSL handshaking to upstream, client: 127.0.0.1, server: localhost, request: "GET /web/internal/stats?action=network-statistics&request=null HTTP/1.1", upstream: "https://50.18.192.173:80/web/internal/stats?action=network-statistics", host: "localhost:50000", referrer: "http://localhost:50000/"

However, if I change the upstream block to:

upstream backend {
  server api-dev.example.com:443;
}

…then I get 404s. Coulda sworn I'd seen similar configurations work elsewhere on Server Fault. For example, this is a very similar question. What am I missing? What could be going wrong? Sorry if this is vague, I'm happy to add more detail.

Best Answer

Try remove /web/. I think you're getting 404 because it tried to accesss /web/web which is not exist. You should be able to find more hint from Nginx logs.

upstream backend {
        server api-dev.example.com:443;
}

server {
        ...

    location / {
        proxy_pass http://localhost:9000;
        ...
    }

    location /web/ {
        proxy_pass https://backend;
        ...
    }
}