如何在Next.js 13中获取客户端的IP地址?

How to get client's ip address in Next.js 13?

提问人:Nusab19 提问时间:9/27/2023 最后编辑:Nusab19 更新时间:9/27/2023 访问量:856

问:

我有一个下一个.js 13应用程序,并想添加一个API端点。/api/getIP

该文件位于 .route.js/app/api/getIP/route.js

最小可复制代码:https://github.com/Nusab19/nextjs-test/tree/main/app

我尝试了几种方法,但没有一种有效。我尝试使用获取 ip,但它返回了 .request-ipnull

第一 attepmt,

这是我的代码:

import { NextResponse } from "next/server";
import requestIp from "request-ip";

export async function GET(req) {
  const detectedIp = requestIp.getClientIp(req);
  const data = {
    ok: true,
    ip: detectedIp,
    userAgent: req.headers.get("user-agent"),
  };
  return new NextResponse(JSON.stringify(data, null, 2));
}

当我访问时,我得到这个回复:

{
    "ok": true,
    "ip": null,
    "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36"
}

第二次尝试:

import { NextResponse } from 'next/server';

export async function middleware(req) {
  const { ip, nextUrl } = req;

  nextUrl.searchParams.set('clientIp', ip);

  return NextResponse.rewrite(nextUrl);
}

export async function GET(req) {
  const data = {
    ok: true,
    ip: req.query.clientIp ?? "127.0.0.1",
    message: "Hello from the API",
  };
  return new NextResponse(JSON.stringify(data, null, 2));
}

在构建过程中出现错误:

Error occurred prerendering page "/api/user". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Cannot read properties of undefined (reading 'clientIp')
下一个.js IP 地址 next.js13

评论

0赞 Golamrabbi Azad 9/27/2023
这回答了你的问题吗?如何在Next.js App中从服务器端获取客户端的IP地址?
0赞 Nusab19 9/27/2023
@GolamrabbiAzad 不,我都试过了

答:

1赞 Robin Thomas 9/27/2023 #1

由于您已经在使用 Next.js 路由器,我假设您在 Vercel 上托管。app

如果是,Vercel 可以使用 Next.js 中间件提供这些信息。

ip: (string || undefined) - 具有请求的 IP 地址。此信息由您的托管平台提供。

https://nextjs.org/docs/pages/api-reference/functions/next-server#nextrequest

您可以通过在存储库的根目录下创建文件来创建 Next.js 中间件(如果您使用的是 ,则应该是 ),内容如下:appmiddleware.jssrc/appsrc/middleware.js

import { NextRequest, NextResponse } from 'next/server';

export async function middleware(req: NextRequest) {
  const { ip, nextUrl } = req;

  nextUrl.searchParams.set('clientIp', ip);

  return NextResponse.rewrite(nextUrl);
}

上面的代码将添加 as 查询参数,然后将其传递给路由处理程序。clientIp

在路由处理程序中,您可以像以下方式访问它:

export async function GET(req) {
  const data = {
    ok: true,
    ip: req.query?.clientIp ?? "127.0.0.1",
    message: "Hello from the API",
  };
  return new NextResponse(JSON.stringify(data, null, 2));
}

缺点是,它不适用于您的本地环境(无论如何您都知道您的本地 IP)和任何不提供此信息的托管平台。


如果不想使用中间件,可以使用请求标头来检索 IP。

export async function GET(req) {
  const data = {
    ok: true,
    ip: req.headers.get("x-real-ip") ?? "127.0.0.1",
    message: "Hello from the API",
  };
  return new NextResponse(JSON.stringify(data, null, 2));
}

评论

0赞 Nusab19 9/27/2023
它托管在 vercel 上。但这种实现也不起作用。代码如下: cutt.ly/Pwv9gaLk 代码中有什么问题吗?
0赞 Robin Thomas 9/27/2023
@NusabTaha-NUSAB19 因为这不是你创建中间件的方式。我已经更新了关于如何创建中间件的答案。你能检查一下它现在是否有效吗?
0赞 Robin Thomas 9/27/2023
@NusabTaha-Nusab19 您的路由处理程序也是错误的。我已经更新了我的答案,以显示如何查询参数。GET
0赞 Nusab19 9/27/2023
我在 中收到此错误。预呈现页面“/api/user”时出错。阅读更多:nextjs.org/docs/messages/prerender-error TypeError:无法读取未定义的属性(读取“clientIp”)npm run build
0赞 Robin Thomas 9/27/2023
@NusabTaha-Nusab19 您还没有创建中间件。它需要位于根目录内。请再读一遍我的回答。middleware.js
1赞 Golamrabbi Azad 9/27/2023 #2

一种较短的方法,不需要使用任何第三方库或服务。

    import { NextRequest, NextResponse } from "next/server";
    import { headers } from "next/headers";
    
    /** @param {NextRequest} req */
    export async function GET(req) {
      const { ua } = userAgent(req);
    
      const headersList = headers();
      const ip = headersList.get("x-forwarded-for");
    
      const data = {
        ok: true,
        ip_address: ip,
        user_agent: ua,
      };
    
      return NextResponse.json(data, { status: 200 });
    }

现在,此代码示例回答了您的问题。

评论

0赞 Nusab19 9/27/2023
这也有效。感谢您的帮助!