Next.js 服务器端 api 调用返回 500 内部服务器错误

Posted

技术标签:

【中文标题】Next.js 服务器端 api 调用返回 500 内部服务器错误【英文标题】:Next.js server side api call returns 500 internal server error 【发布时间】:2020-05-10 07:07:12 【问题描述】:

我终于开始涉足使用Next.js 进行服务器端反应的世界,但是我对这个问题感到很困惑。

我正在使用 isomorphic-unfetchpages/customer-preferences.tsx 调用 API

CustomerPreferencesPage.getInitialProps = async () => 
  const res = await fetch(API_URL + '/preference-customer');
  const initialData = await res.json();
  return  initialData ;
;

dev 模式下或一旦构建并运行build > start,一切都可以正常工作。为了托管它,我从 docker 容器 node:10 运行它,当我在本地运行它时,一切都很好。该问题仅在部署后才会发生。

当我导航到/,然后单击指向/customer-preferences 的链接时,一切都按预期工作。但是,如果我刷新页面或直接在 /customer-preferences 加载页面,我会从 Next.js 看到此错误

所以这个问题似乎只发生在尝试从服务器而不是客户端进行 API 调用时。

我还设置了一个简单的快速服务器来代替使用,但不确定是否有必要?!

const express = require('express');
const next = require('next');

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next( dev );
const handle = app.getRequestHandler();

app.prepare().then(() => 
  const server = express();

  server.all('*', (req, res) => 
    return handle(req, res);
  );

  server.listen(port, err => 
    if (err) throw err;
    console.log(`> Ready on http://localhost:$port`);
  );
);

当检查服务器日志时,我得到了这个:

FetchError: request to http://xxx failed, reason: getaddrinfo EAI_AGAIN xxx xxx:80

任何帮助将不胜感激。

【问题讨论】:

这对您有帮助吗? github.com/nodejs/node/issues/15780#issuecomment-425930255 @MichalisGarganourakis 是的,看到了,但该线程上也没有任何回应 @xadm 我需要一个混合应用程序。这适用于完全静态的应用程序 不要使用绝对 URL,使用可以解决问题的相对 URL @divyang4481 API 与应用无关 【参考方案1】:

我的怀疑与fetch 不是本机节点模块而是浏览器中的客户端这一事实有关。所以,如果你从一个页面导航到这个页面;根据文件; getInitialProps 将从客户端调用,使fetch 方法可访问。刷新确保从服务器端调用的 getInitialProps。

您可以通过从浏览器的检查器和节点 REPL 运行 typeof fetch 来测试这个理论。

您最好从组件调用方法或使用第三方 HTTP 客户端,如 axios...

如果你想跳过从后端调用 AJAX 方法而只从前端调用它,你可以测试该方法是从前端调用还是从后端调用,如下所示:

CustomerPreferencesPage.getInitialProps = async () => 
  if (typeof window === 'undefined') 
    // this is being called from the backend, no need to show anything
    return  initialData: null ;
  

  const res = await fetch(API_URL + '/preference-customer');
  const initialData = await res.json();
  return  initialData ;
;

【讨论】:

I'm making a call to an API from pages/customer-preferences.tsx using isomorphic-unfetch @cr05s19xx 不完全是。同构 这里的罪魁祸首,但这与模块导入无关。问题是getInitialProps 是同构的,因此在客户端和服务器上调用 Docker 主机名。主机名在客户端公开为 localhost。【参考方案2】:

不,不需要服务器设置。

发生这种情况是因为浏览器/客户端无法解析 docker 容器的主机名。就目前而言,我知道的唯一解决方案是检查 getInitialProps 中的 req 对象(以确定提取将在哪个环境中运行)并在服务器上调用 Docker 主机名,在客户端调用 localhost。例如。

async getInitialProps (ctx) 
    if (ctx.req) // ctx.req exists server-side only
    
        // call docker-host:port
    
    else 
        // call localhost:port
    

【讨论】:

以上是关于Next.js 服务器端 api 调用返回 500 内部服务器错误的主要内容,如果未能解决你的问题,请参考以下文章

Next.js 500 内部服务器错误在 404 页面内调用 useEffect Hook 后立即出现

Next Js 服务端 Api 读写 JSON

如何处理调用 API 的 Next.js 中动态路由的未找到 404?

Next Js API:使用 s-s-r 反应页面的响应

我应该开发一个单独的快速服务器,还是在我的 next.js 应用程序中处理所有 API 调用?

Next.js + API 在同一台服务器上