How to proxy Node.js error responses on NGINX?

July 26, 2017 183 views
Nginx Node.js Ubuntu 16.04

I have an application server that is running a Sails.js Node application on top of NGINX. The application appears to be working correctly, however when the server accepts/rejects a request, the response body is empty. The response code is correct, however the body is completely empty. I can verify that the app is generating the correct responses using the applications debugging that I have in place.

This is the NGINX configuration that I have in place:

upstream local-upstream {
        server 127.0.0.1:8080;
        keepalive 64;
}
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        return 301 https://$host$request_uri;
}
server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        ssl on;
        ssl_certificate XXX;
        ssl_certificate_key XXX;
        ssl_prefer_server_ciphers on;

        ## OCSP Stapling
        resolver 127.0.0.1 8.8.8.8 8.8.4.4 valid=300s;
        resolver_timeout 5s;
        ssl_stapling on;
        ssl_stapling_verify on;
        ssl_trusted_certificate XXX;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        #server_name _;
        server_name app.quiqmath.com;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                #try_files $uri $uri/ =404;
                proxy_pass http://local-upstream;
                proxy_redirect off;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';
                proxy_set_header Host $host;
                proxy_cache_bypass $http_upgrade;
        }
2 Answers
dniccumdesign July 28, 2017
Accepted Answer

Hi @jtittle I was able to speak with the developer of the Sails.js platform. Apparently there was some code hidden away that clears out the data response in production environments within certain types of responses. A 400 response happen to be one of those responses. I am super sorry for the confusion.

@dniccumdesign

In place of:

    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;

Please try:

        proxy_buffers 16 32k;
        proxy_buffer_size 64k;
        proxy_busy_buffers_size 128k;
        proxy_cache_bypass $http_pragma $http_authorization;
        proxy_connect_timeout 59s;
        proxy_hide_header X-Powered-By;
        proxy_http_version 1.1;
        proxy_ignore_headers Cache-Control Expires;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
        proxy_no_cache $http_pragma $http_authorization;
        proxy_pass_header Set-Cookie;
        proxy_read_timeout 600;
        proxy_redirect off;
        proxy_send_timeout 600;
        proxy_temp_file_write_size 64k;
        proxy_set_header Accept-Encoding '';
        proxy_set_header Cookie $http_cookie;
        proxy_set_header Host $host;
        proxy_set_header Proxy '';
        proxy_set_header Referer $http_referer;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Original-Request $request_uri;

Once those changes are made, please restart NGINX:

service nginx restart

If you run in to any errors along the way, please tail the logs and let's take a look:

tail -25 /var/log/nginx/error.log
  • No new errors appeared within the log, however it appears that nothing has changed.

    I am getting this new error in my Javascript console

    WebSocket connection to 'wss://app.quiqmath.com/socket.io/?__sails_io_sdk_version=0.11.0&__sails_io_…sdk_language=javascript&EIO=3&transport=websocket&sid=tcvJAMseOmE9UmyCAAAG' failed: Error during WebSocket handshake: Unexpected response code: 400
    
  • @jtittle I did go back in and re-add the following block and it fixed my websocket problem:

    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    

    However, I am still not seeing any changes in the POST request response data/body.

  • @jtittle any updates on this?

    • @dniccumdesign

      With the new configuration in place, the issue, to me, would seem to be one with the app.

      When NGINX is set up to proxy a request, it will respond with the response from the app. If the application responds with a blank response to a post request, NGINX will provide that response as it really doesn't know anything about your application or NodeJS in general.

      It's just a middle-man between the incoming request and response sent back.

      The only time NGINX should throw an error is if it's unable to pass a request to the application, or the application is down -- which is most likely why there's not an error in the error logs for NGINX.

      The best test for this would be to stop NGINX and bind the application to a port and public IP. You can use 0.0.0.0 or the IP of the Droplet. Once you've done that, test a port request to the application using the port it's running on and see if the issue persists.

      If you still receive a blank response when only the application is running, then you'd need to look deeper in to the application to see if you can troubleshoot or dump the console on the request to see if that'll provide more information :-).

      NGINX, in this case, is just accepting a request, passing it over to your application, and then waiting for a response and data, if any is passed on in the response.

Have another answer? Share your knowledge.