4

Below is a pretty standard nginx proxy_pass setup:

server {
  listen 80;
  server_name ireport.jungdigital.com;
  access_log /var/log/nginx/ireport.access.log;
  root /var/www/ireport.jungdigital.com/dist;
  index index.html index.htm;
  location / {       
  }
  location /api/ {
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Reques
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Reques
     }
     if ($request_method = 'PUT') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Reques
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Reques
     }
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header X-NginX-proxy true;
     proxy_set_header Host ireport.somehost.org;
     proxy_pass http://ireport_dyndns/api/;
     proxy_ssl_session_reuse off;
     proxy_redirect off;
  }
}

The API that I'm proxying returns response body's that contain error information for 400, 404, and 500 error codes. For example, on a 404, my response body might look like:

{
  "errorCode": "TOKEN_NOT_FOUND",
  "errorMessages": [
    "Could not find a matching authorization token."
  ]
}

If I perform the request without the proxy, I get the response bodies for the errors.

If I use the nginx proxy, for some reason the response bodies are swallowed by nginx and I can't even see a response at all in my web browser Network tab.

Is there a way to tell Nginx to return response bodies for error codes in a proxy_pass?

JoshuaJ
  • 929
  • 1
  • 9
  • 22
  • Read carefully http://nginx.org/r/add_header – Alexey Ten May 05 '16 at 12:04
  • @AlexeyTen It's not a header I need, it's the response body itself. I did some more digging and it appears the body is actually returned but is being swallowed by the browser itself. – JoshuaJ May 05 '16 at 12:46
  • That's because browsers need headers to allow access to response body. I guess, you need `always` flag for `add_header` – Alexey Ten May 05 '16 at 12:50
  • @AlexeyTen So I've actually compared the response headers from a direct request and a proxied request and they are the same. The only things different are that a proxied request from the browser contains a Origin and Referrer header for localhost and non-proxied request contains a X-Requested-With header. – JoshuaJ May 05 '16 at 12:57
  • Show full server config\ – Alexey Ten May 05 '16 at 13:01

3 Answers3

5

I run into same question recently.

And the last anwser is that: add proxy header Upgrade

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';

My full config as following:

upstream cloud-api {
        server 127.0.0.1:8089;
}

client_max_body_size 20M;
client_header_buffer_size 8k;
large_client_header_buffers 4 16k;

server {
        listen 8001;
        access_log  /data/senseid-cloud-log/senseid-cloud-api-access.log;
        error_log  /data/senseid-cloud-log/senseid-cloud-api-error.log warn;

        location / {
                proxy_http_version 1.1;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection 'upgrade';

                proxy_read_timeout 300s;
                proxy_pass http://cloud-api;
        }
}

And you could catch 500/401 .etc error body

Details : http://nginx.org/en/docs/http/websocket.html

Hope to give you some help.

NorthWind
  • 66
  • 1
  • 2
1

See How to add a response header on nginx when using proxy_pass?

  1. Per Alexey's comment - "browsers need headers to allow access to response body. I guess, you need always flag for add_header"
  2. Since nginx 1.7.5 you can use the keyword always to include headers even in error responses - so you can setup your nginx.conf as follow:

-

server {
    server_name  .myserver.com
    location / {
        proxy_pass  http://mybackend;
        add_header X-Upstream $upstream_addr always;
    }
}
David Tobiano
  • 1,188
  • 8
  • 10
0

Today I move Laravel 5.2 from IIS 8.5 to Ubuntu 16.04 (Nginx 1.10.0 - PHP-FPM 7.0.10), I have same problem. The body response from server are always empty when request from Angular2. But the postman still get body on response. So that must be problem with request headers.

This config help me solved problem above:

    add_header 'Access-Control-Allow-Origin' '*' 'always';
    add_header 'Access-Control-Allow-Credentials' 'true' 'always';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, PUT, OPTIONS, HEAD' 'always';
    add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' 'always';

Third parameters for add_header only available in recent nginx version.

xCiCi
  • 147
  • 2
  • 9