NextJs:Nginx 在 API 路由上返回 404

问题描述 投票:0回答:2

我在这里遇到一个问题,在生产中重新加载页面期间从

getInitialProps
执行时,我的 NextJs API 返回 404 not found。

我的 PM2 日志中的错误消息提到 Nginx 返回了 404 not found。

NGINX 似乎无法检测到我在

/api/*
中的路线。

这个问题不会发生在本地,我怀疑这是我在 nginx 中错过的问题或配置。

这是我当前使用的版本

  1. NextJs:9.4.0
  2. nginx/1.18.0 (Ubuntu) - 在 AWS EC2 上

更新

如果我在 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({})
        }
    }
}

PM2 日志错误 enter image description here

nginx next.js
2个回答
3
投票

已解决

显然这个问题是由 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;
  }
}

0
投票

对我来说,只需注释掉“try_files $uri $uri/ =404;”行内部位置 / { } 因为正如 Dexter 提到的

“我们需要删除这个 404 处理,因为 next 的 _next 文件夹和 nextjs 自己处理 404”

© www.soinside.com 2019 - 2024. All rights reserved.