我在这里遇到一个问题,在生产中重新加载页面期间从
getInitialProps
执行时,我的 NextJs API 返回 404 not found。
我的 PM2 日志中的错误消息提到 Nginx 返回了 404 not found。
NGINX 似乎无法检测到我在
/api/*
中的路线。
这个问题不会发生在本地,我怀疑这是我在 nginx 中错过的问题或配置。
这是我当前使用的版本
更新
如果我在 nginx.conf 文件中禁用 SSL,我可以将问题范围缩小到 SSL 问题。 API 运行良好。但是我仍然无法找到解决方案。
nginx 配置文件
server {
# Your domain
server_name mydomain.com;
# Proxy to nuxt renderer.
location / {
auth_basic "Restricted Content";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $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 X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
}
# Redirect from /path/ to /path
rewrite ^/(.*)/$ /$1 permanent;
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/mydomain.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/mydomain.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = mydomain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name mydomain.com;
return 404; # managed by Certbot
}
NextJs getInitialProps 代码
static async getInitialProps(context) {
const isServer = !!context.req
const { employerAccessToken } = nextCookie(context)
api.setBaseURL('/')
api.setAuthToken(employerAccessToken)
if (isServer) {
api.setCookie(nextCookie(context))
}
let apiResponse = await api.get('/api/employer/profile')
if (!apiResponse.ok) {
console.log('not OK');
console.log(apiResponse);
redirectToEmployerLogin(context)
return {}
}
let wrappedProps = {}
if (WrappedComponent.getInitialProps) {
wrappedProps = await WrappedComponent.getInitialProps(context)
}
}
api/雇主/个人资料
const handler = async (req, res) => {
if (req.method == 'GET') {
try {
const { employerAccessToken } = nextCookie({ req, res })
api.setBaseURL(process.env.NEXT_PUBLIC_API_URL)
api.setAuthToken(employerAccessToken)
const apiResponse = await api.get('/employers/me', req.query)
console.log('apiResponse in /api/employer/profile');
console.log(apiResponse);
res.status(apiResponse.status).json(apiResponse.data)
} catch (error) {
logger.error(`message - ${error.message}, stack trace - ${error.stack}`)
res.status(500).json({})
}
}
}
已解决
显然这个问题是由 nginx 将服务器请求从 http 重定向到 https 引起的,但是 NextJs 在 https 中无法识别路由,因此 Nginx 返回 404 not find。
解决方案是允许本地主机的代理通行证在端口 80 上维护请求,而不是将所有端口 80 请求转发到 443。
server_blockconf
# redirect http to https
server {
listen 80;
listen [::]:80;
server_name 127.0.0.1 localhost;
location / {
proxy_pass http://localhost:3000;
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;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name yourserver.com www.yourserver.com;
return 301 https://$server_name$request_uri;
}
server {
# listen on *:443 -> ssl;
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name yourserver.com;
ssl_certificate /etc/letsencrypt/live/yourserver.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/yourserver.com/privkey.pem; # managed by Certbot
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
location / {
# reverse proxy for next server
proxy_pass http://localhost:3000;
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;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
# we need to remove this 404 handling
# because next's _next folder and own handling
# try_files $uri $uri/ =404;
}
location ~ /.well-known {
allow all;
}
}
对我来说,只需注释掉“try_files $uri $uri/ =404;”行内部位置 / { } 因为正如 Dexter 提到的
“我们需要删除这个 404 处理,因为 next 的 _next 文件夹和 nextjs 自己处理 404”