NginX 在将请求从静态捆绑包代理到 Express 后端时无法传递 POST 请求正文



我正在运行一个托管在'pocket-caravan.com'的数字海洋液滴上的NginX服务器。

目标是构建反应包,该包将链接到所有css/js/images,并使用nginx来处理提供静态内容。 API 服务器是一个在某个端口上运行的 Express 应用程序,我将静态捆绑包中的所有请求代理到此端口。

当我在本地开发时,我能够将 JSON 数据从前端发送到我的 API。

当我部署我的 API 时,我可以通过 Postman 发送 JSON 有效负载

但问题是,当我通过访问 NginX 提供的静态文件转到我的应用程序时,我向实时 API 发送 POST 请求,req.body是空的!

我可以检查 JS 控制台并查看获取请求是否正确发送 JSON 数据正文。

请求已正确路由到实时 API,但数据为空!NginX 代理不传递请求正文,我不知道为什么??

我有一个问题 - 虽然我可以访问所有静态文件,但我的 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/

发送开机自检请求https://pocket-caravan.com/api/register?pathway=marketplace

示例 JSON 数据: { "名字": "foo", "姓氏": "酒吧", "电子邮件": "foo@bar.com", "密码":"123123">
}

在端口 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}`);
});

当我将请求发送到https://pocket-caravan.com/api/register?pathway=marketplace时,这在 localhost - webpackdevserver 工作正常

但是,当部署的构建代码从代理请求的同一 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"

我想出了问题所在。很简单。我未能将正确的"内容类型"标头传递给代理。我查看了请求输出,并在期望传递 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;
}

可能会帮助其他人,所以我遇到了与此相同的问题,收到了 url 调用但没有数据。按照接受的答案中的建议编写nginx配置后,问题仍然存在。然后我发现我需要调用服务器不是使用 http 而是使用 https。因此,如果您仍然像我一样坚持,请检查您的网址。

不知道为什么使用 http 的呼叫在没有数据的情况下路由,但它确实如此。

我遇到了这个问题。我发现磁盘已满,所以 rm 一些大目录,问题得到解决

最新更新