NginX не удается передать тело запроса POST при прокси-запросах к Express бэкэнду из пакета stati c - PullRequest
0 голосов
/ 08 января 2020

Я использую сервер NginX, размещенный на Digital Ocean Droplet по адресу pocket-caravan.com.

Цель состояла в том, чтобы создать пакет реакции, который будет ссылаться на все css / js / images и используйте nginx для обработки содержимого stati c. Сервер API - это приложение Express, которое работает на каком-то порту, и я передаю на него все запросы из пакета stati c.

При локальной разработке я могу отправить JSON данные в мой API из внешнего интерфейса.

Когда я развертываю свой API, я могу отправлять JSON полезных нагрузок через Postman

Но ПРОБЛЕМА заключается в том, что когда я go в мое приложение при доступе к файлам stati c, обслуживаемым NginX, и отправке запроса POST в действующий API, req.body пусто!

Я могу осмотреть консоль JS и убедиться, что запрос на выборку правильно отправляет тело данных JSON.

Запрос правильно перенаправляется в действующий API, но данные пустой! Прокси NginX не передает тело запроса, и я не знаю, почему ??

У меня есть проблема - хотя я могу получить доступ ко всем файлам stati c, мои запросы API передаются через прокси и правильно направляется в API, но когда Express обращается к req.body, оно пустое!

/etc/nginx/sites-available/pocket-caravan.com

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




}

Воспроизведение этой проблемы:

Я получаю доступ к своему приложению: https://pocket-caravan.com/omni-commerce/

Отправить запрос POST https://pocket-caravan.com/api/register?pathway=marketplace

Пример JSON data: {"firstName": "foo", "lastName": "bar", "email": "foo@bar.com", "password": "123123"
}

Express Приложение, работающее на порту 3001:

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) => {
    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 => {
    if (connection.success) {
      console.log(connection.message);
    };
  }).catch(err => {
    console.log("Catching mongoose error...")
    console.log(err);
  })


app.get('/', (req, res) => {
  res.send('GET /')
});

app.get('/api', (req, res) => {
  res.send('GET /api')
});

app.use('/api', usersRouter);

// Universal Error Handler
app.use('*', (err, req, res, next) => {
  handleError(err);
  res.status(err.status || 500).json({ error: err.stack, message: err.message });
})

app.listen(process.env.PORT, () => {
  console.log(`Server listening on port ${process.env.PORT}`);
});

Это прекрасно работает с localhost - webpackdevserver, когда я отправляю запрос на https://pocket-caravan.com/api/register?pathway=marketplace

Однако, когда развернуто встроенный код обслуживается с того же сервера NginX, который проксирует запросы, тело запроса недоступно Express.

Я недостаточно знаю о NginX, чтобы продолжить отладку, я не могу зарегистрировать тело запроса, я был бы очень признателен за любую помощь!

Вот информация от панель «Сеть» об отказавшем запросе: (выдает 500, поскольку req.body.email не определен и вылетает промежуточное ПО)

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"

1 Ответ

0 голосов
/ 08 января 2020

Я понял проблему. Это было просто. Мне не удалось передать правильный заголовок «Content-Type» прокси. Я посмотрел на вывод запроса и увидел это, ожидая, что он передаст JSON:

Content-Type: text/plain;charset=UTF-8

Express body-parser / json -parser не проанализировал тело и не передал его req.body.

Добавление этого в мой обработчик прокси /api исправило следующие вещи:

proxy_set_header content-type "application/json";

    location /api {
        proxy_pass http://localhost:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Host $host;
        proxy_set_header content-type "application/json";
        proxy_cache_bypass $http_upgrade;
        proxy_set_header Connection 'upgrade';
        access_log /var/www/pocket-caravan.com/logs/logs.txt;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...