Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting a 502 bad gateway when sending a redirect from behind amazon elastic load balancer?

I'm trying to redirect any HTTP requests to my server over to HTTPS.

ELB is listening on port 80 and forwarding all request to port 8088 on my application. The application then sends a 301 Moved Permanently response redirecting to the same URL, but with any ports stripped off and 'https://' prepended. This causes clients to re-request the url over HTTPS.

When I test it locally it works fine, but when I deploy it to EC2 behind an Elastic Load Balancer I get 502 Bad Gateway coming back. The server is receiving the request and appears to be sending the redirect correctly (as I said, it works when I hit the server directly, not via a load balancer).

like image 377
Darren Avatar asked Oct 04 '22 09:10

Darren


1 Answers

It turns out that ELB is very picky about what it considers a 'valid' response and will return 502 Bad Gateway if it isn't happy. I fixed it by making sure the response from my server had the following headers:

eg. if I was listening at http://example.com

I send back the following response:

HTTP/1.1 301 Moved Permanently
Content-Type: */*; charset="UTF-8"
Location: https://example.com/
Content-Length: 0

This makes ELB happy and everything works.

For interest, here's the code (Java, using Simpleframework):

private static void startHttpsRedirector() throws IOException {
    org.simpleframework.http.core.Container container = new org.simpleframework.http.core.Container() {
        @Override
        public void handle(Request request, Response response) {
            Path path = request.getPath();
            Query query = request.getQuery();
            String rawHost = request.getValue("host");

            System.out.println("Raw host: " + rawHost);
            System.out.println("Raw path: " + path);
            System.out.println("Raw query: " + query);

            String host = rawHost.replaceFirst("\\:.*", "");
            response.setStatus(Status.MOVED_PERMANENTLY);
            String redirectTo = "https://" + host + path + (query.values().size() > 0 ? "?" + query : "");

            System.out.println("redirectTo = " + redirectTo);
            response.setContentType("*/*; charset=\"UTF-8\"");
            response.setValue("Location", redirectTo);
            response.setContentLength(0);
            try {
                response.commit();
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
    Server server = new ContainerServer(container);
    Connection connection = new SocketConnection(server);
    SocketAddress address = new InetSocketAddress(8088);
    connection.connect(address);
}

The same code in javascript can be found here: https://gist.github.com/dhobbs/6164710

like image 64
Darren Avatar answered Oct 13 '22 10:10

Darren