title: NginX fails to pass of POST request body when proxying requests to an Express backend from static bundle
body: <p>I am running an NginX server hosted on a Digital Ocean Droplet at 'pocket-caravan.com'.</p>
  
  <p>The goal was to build the react bundle which would link to all css/js/images and use nginx to handle serving static content. 
  The API server is an Express app which is running on some port, and I proxy all requests from the static bundle to this.</p>
  
  <p>When I develop locally, I am able to send JSON data to my API from the front-end.</p>
  
  <p>When I deploy my API, I can send JSON payloads through Postman </p>
  
  <p>But the PROBLEM is that when I go to my app by accessing the static files served by NginX, and I send a POST request to the live API, the <code>req.body</code> is empty! </p>
  
  <p>I can inspect the JS console and see that the fetch request is correctly sending a JSON data body.</p>
  
  <p>The request is routed to the live API correctly, but the data is empty! The NginX proxy does not pass along the request body and I don't know why??</p>
  
  <p>I have a problem - While I can access all the static files, my API requests are being proxied and routed correctly to the API, but when Express accesses <code>req.body</code>, it's empty! </p>
  
  <p><code>/etc/nginx/sites-available/pocket-caravan.com</code></p>
  
  <pre><code>server {
  
      root /var/www/pocket-caravan.com/html;
      index index.html index.html index.nginx.debian.html;
  
      server_name pocket-caravan.com www.pocket-caravan.com;
  
  
      location /omni-commerce {
          index index.html;
      }
  
      location /static {
          try_files /omni-commerce/$uri /omni-commerce/$uri/;
      }
  
      location /api {
          proxy_pass http://localhost:3001;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
          proxy_set_header Connection 'upgrade';
          access_log /var/www/pocket-caravan.com/logs/logs.txt;
      }
  
  
      listen [::]:443 ssl ipv6only=on; # managed by Certbot
      listen 443 ssl; # managed by Certbot
      ssl_certificate /etc/letsencrypt/live/pocket-caravan.com/fullchain.pem; # m$
      ssl_certificate_key /etc/letsencrypt/live/pocket-caravan.com/privkey.pem; #$
      include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
      ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
  
  }
  server {
      if ($host = www.pocket-caravan.com) {
          return 301 https://$host$request_uri;
      } # managed by Certbot
  
      if ($host = pocket-caravan.com) {
          return 301 https://$host$request_uri;
      } # managed by Certbot
      listen 80;
      listen [::]:80;
  
      server_name pocket-caravan.com www.pocket-caravan.com;
      return 404; # managed by Certbot
  
  
  
  
  }
  
  </code></pre>
  
  <p>Reproducing this problem:</p>
  
  <p>I access my app:
  <code>https://pocket-caravan.com/omni-commerce/</code></p>
  
  <p>Send a POST request
  <code>https://pocket-caravan.com/api/register?pathway=marketplace</code></p>
  
  <p>Sample JSON data: 
  {
  "firstName": "foo",
  "lastName": "bar",
  "email": "foo@bar.com",
  "password": "123123"<br>
  }</p>
  
  <p>Express App running at port 3001:</p>
  
  <pre class="lang-js prettyprint-override"><code>import util from 'util';
  import helmet from 'helmet';
  import express from 'express';
  import cookieParser from 'cookie-parser'
  import morgan from 'morgan';
  import { handleError } from '../lib/utils/logger';
  import getEnv from '../lib/utils/get-env';
  
  import { establishMongooseConnection } from '../lib/mongo/mongoose-db';
  import { usersRouter } from './router/users';
  
  getEnv()
  
  const app = express();
  
  app.use(morgan('common'));
  app.use(express.json());
  app.use(express.urlencoded({ extended: true }));
  app.use(cookieParser());
  app.use(helmet());
  
  if (app.get('env') === 'development') {
    console.log('Configuring Access Control Allow Origin header for Local Development.');
    app.use('*', (req, res, next) =&gt; {
      res.header(
        'Access-Control-Allow-Origin',
        `${req.get('origin')}`,
      );
      res.header(
        'Access-Control-Allow-Headers',
        'Origin, X-Requested-With, Content-Type, Accept, Authorization, Set-Cookie',
      )
      res.header(
        'Access-Control-Allow-Methods',
        'POST, GET, OPTIONS, DELETE, PUT'
      )
      res.header('Access-Control-Allow-Credentials', true);
      next();
    });
  }
  
  if (app.get('env') === 'production') {
    // Trust DigitalOcean - NginX Proxy 
    // https://expressjs.com/en/guide/behind-proxies.html
    app.set('trust proxy', 'loopback', process.env.DIGITAL_OCEAN_DROPLET_IP)
  }
  
  establishMongooseConnection()
    .then(connection =&gt; {
      if (connection.success) {
        console.log(connection.message);
      };
    }).catch(err =&gt; {
      console.log("Catching mongoose error...")
      console.log(err);
    })
  
  
  app.get('/', (req, res) =&gt; {
    res.send('GET /')
  });
  
  app.get('/api', (req, res) =&gt; {
    res.send('GET /api')
  });
  
  app.use('/api', usersRouter);
  
  // Universal Error Handler
  app.use('*', (err, req, res, next) =&gt; {
    handleError(err);
    res.status(err.status || 500).json({ error: err.stack, message: err.message });
  })
  
  app.listen(process.env.PORT, () =&gt; {
    console.log(`Server listening on port ${process.env.PORT}`);
  });
  
  </code></pre>
  
  <p>This works fine from localhost - webpackdevserver when I send the request to <code>https://pocket-caravan.com/api/register?pathway=marketplace</code></p>
  
  <p>However, when the deployed built code is served from the same NginX server that proxies the requests, the request body is inaccessible by Express. </p>
  
  <p>I don't know enough about NginX to proceed debugging this, I can't seem to log the request body, I would really appreciate any help!</p>
  
  <p>Here is the info from the Network panel about the failed request:
  (Throws 500 since req.body.email is undefined and crashes middleware)</p>
  
  <pre><code>General
  Request URL: https://pocket-caravan.com/api/register?pathway=omni
  Request Method: POST
  Status Code: 500 Internal Server Error
  Remote Address: 67.205.154.96:443
  Referrer Policy: no-referrer-when-downgrade
  
  Response Headers
  Access-Control-Allow-Credentials: true
  Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, Set-Cookie
  Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT
  Access-Control-Allow-Origin: https://pocket-caravan.com
  Connection: keep-alive
  Content-Length: 1633
  Content-Type: application/json; charset=utf-8
  Date: Wed, 08 Jan 2020 08:52:16 GMT
  ETag: W/"661-PIPnVrxYNILoG0ylml9L0Camw1w"
  Server: nginx/1.14.0 (Ubuntu)
  Strict-Transport-Security: max-age=15552000; includeSubDomains
  X-Content-Type-Options: nosniff
  X-DNS-Prefetch-Control: off
  X-Download-Options: noopen
  X-Frame-Options: SAMEORIGIN
  X-XSS-Protection: 1; mode=block
  
  Request-Headers
  Accept: application/json
  Accept-Encoding: gzip, deflate, br
  Accept-Language: en-US,en;q=0.9
  Connection: keep-alive
  Content-Length: 94
  Content-Type: text/plain;charset=UTF-8
  Cookie: Stuff=random--!; Authorization-Omni=sec0ret%20encu0ingdgin
  DNT: 1
  Host: pocket-caravan.com
  Origin: https://pocket-caravan.com
  Referer: https://pocket-caravan.com/omni-commerce/
  Sec-Fetch-Mode: no-cors
  Sec-Fetch-Site: same-origin
  User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36
  pathway: omni
  {firstName: "asdasda", lastName: "asdas", email: "asdasd@adsda.com", password: "asdasdsdasd"}
  firstName: "asdasda"
  lastName: "asdas"
  email: "asdasd@adsda.com"
  password: "asdasdsdasd"
  </code></pre>