Nestjs 如何获取请求的 IP

前言

本来想随手一搜就出来答案,结果都是些什么博文?可见中文环境下的垃圾信息充斥程度。甚至还要特别安装 request-ip 包?

不能忍,于是只能顺手自己摸索,并贴出自己的答案。

普通情况

只需要使用 @Requst 属性修饰器,即可拿到 Express 的 Request 对象。如下:

import {
  Body,
  Request,
  Post,
  Controller,
} from '@nestjs/common';
import { Request as ExpRequest } from 'express';

@Controller('content')
export class ContentController {
	@Post()
	async postContent(
    	@Request() req: ExpRequest,
    	@Body() body: CreateLogDTO,
  ): Promise<any> {}
}

在 Express Reqeust 对象中,有ip属性,直接索引即可拿到:

const ip = req.ip

拿到的字符串类似:

::ffff:127.0.0.1

前面是 ipv6,后面是 ipv4。相信以目前国内环境来说,大部分的情况下只需要 ipv4。获取ipv4可以用简单的字符串处理方法进行处理:

if (ip.indexOf('::ffff:') !== -1)
{
    ip = ip.substring(7)
}

如果需要ipv6也可以反过来操作。操作后IP输出类似:

127.0.0.1

Nginx代理的情况

nginx 代理转发到 backend 下,就不能直接拿 IP 了,否则拿到的都是代理 nginx 的 IP(比如可能是本机 127.0.0.1 也可能是其他的内网地址),也就失去了意义。

这个时候需要如下步骤。

nginx配置携带自身代理的真实请求地址到 header

修改nginx的代理配置,添加如下 header

proxy_set_header X-Real-IP			$remote_addr;

注意配置是代理配置,非 nginx 程序配置,有关 nginx 配置可另行解说,在此不再讨论。其中 X-Real-IP 是自定义的 header,可以修改成自己喜欢的、独特的字段。一般自定义的头,都会以 X 开头,以与标准 header 作区分。

在 Nestjs 中读取头

如下(前略):

@Post()
async postContent(
    @Request() req: ExpRequest,
    @Headers('x-real-ip') headerRealIP: string,
  ): Promise<any> {
    console.log(req.ip);
    console.log(headerRealIP);
  }

注意这个修饰符里填入的头,是不区分大小写的(RFC 2616 -“HTTP / 1.1”,第4.2),按照习惯填写即可。

AWS的 CloudFront 代理情况

情况类似自定义 nginx 头,CF 会把请求 IP 放在 x-forward-for 头里带上来。需要注意的是头里同样包含了 ipv4 跟 ipv6 两种地址,需要字符串处理分开取用。

关键代码如下:

@Post()
async postContent(
    @Request() req: ExpRequest,
    @Headers('x-forwarded-for') headerRealIP: string,
  ): Promise<any> {
    let ip = headerRealIP.split(", ")[0]
    console.log(ip)
}

综合使用

像阿里云、腾讯云的 CDN 或者 DCDN 代理原理都类似,需要查阅对应平台的自定义标头部分定义。

在代码里,先判断各种平台携带的真实 IP 的标头是否有值,有值则采用对应平台的策略,如果都没值,则使用 Express 里的 Request 下的 ip 值。

这样代码就可以通用于所有环境来获取请求发起的 IP 地址了。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值