转发源请求的元数据
前面的章节说道,在 SSR 场景中,Next.js 渲染服务器向 API 服务器请求数据时,其实是反向代理了真实的用户请求。
如上图所示,通过渲染服务器发送的请求并不会转发真实用户请求的头部信息和 IP 等其他信息。而如果不转发这些信息,那么对于数据分析或者需要使用 IP 或者 ua 的场景就会非常不友好,例如 rate limit 我们一般使用 ua 或者 IP 作为标识符。
所以这节我们对这些请求做特殊处理。
在 Page Router 下
在传统的路由模式中,渲染服务器发送的请求一般在 getInitialProps
或者 getServerSideProps
方法内部。
下面的例子用我们使用 axios
作为请求库,当然你可以选择其他。
我们先以 getServerSideProps
为例。
getServerSideProps
接受一个 ctx 对象,其中包含 req: ImcomingMessage
对象。从上面我们可以获取到原始请求的 headers 和 ip 信息。
那么在渲染服务器发送请求之前,我们需要对把元数据注入到请求实例中。
我们可以封装一个方法实现:
上面的方法中可以把原始请求中的 user-agent 附加到请求示例中,提取真实 ip 附加到 headers 的 x-forwarded-for
上。随后还可以针对 token 等其他信息的转发。
然后这样使用。
在 getInitialProps
中使用方式也大同小异。
但是由于 getInitialProps
会在 Client 和 Server 端混合执行,所以需要对 attachRequestProxy
方法加一点判断。
然后这样使用。
我们来看看效果。写一个接口 /api/test
如下:
本地启动 dev server,然后我们使用内网地址访问 http://10.0.0.89:9999
(这是我的环境,按需修改。)
随后得到 server 的控制台输出:
可以看到 user-agent
和 x-forwarded-for
都是源请求的数据。
上面的例子位于:https://github.com/innei-dev/nextjs-book/tree/main/demo/request-proxy-pages
在 App Router 下
在 App Router 下,即使在 Server Component 中我们也是无法获取到 req: ImcomingMessage
的,原因是在这个模式下,组件和组件是可被拆分渲染的,所以我们无法在任何地方获取 req
,除非在 middleware 中。但是 middleware 中我们不会做任何 UI render 和数据请求。
这里我们可以使用 headers()
方法获取 req
的 headers
,仅限于在 Server Component 中取到。
Note我们可以安装
server-only
来确保只有在 Server Side 引用该文件。
编写 App router 下的测试 api。
访问 内网地址,输出:
可以看到 x-forwarded-for
正确的附加了源请求的 IP,并且 user-agent
也是源请求的。
最后更新于 2024/7/26 16:15:59
本书还在编写中..
前往 https://innei.in/posts/tech/my-first-nextjs-book-here#comment 发表你的观点吧。