首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >获取Deno中的远程客户端IP地址

获取Deno中的远程客户端IP地址
EN

Stack Overflow用户
提问于 2022-02-06 14:30:27
回答 1查看 524关注 0票数 2

如何在Deno中获取客户端的IP地址?

我已经使用标准的http库创建了一个测试服务器,但是我无法找到一种提取客户端IP的方法。我需要作为一个安全功能,以防止多次提交。

在NodeJS/Express中,request对象有一个相同的request属性。req.ip在Express中给出了我想要的东西,但是在Deno中它相当于什么呢?

我的代码是:

代码语言:javascript
运行
复制
import { serve } from "https://deno.land/std@0.125.0/http/server.ts";

serve(
    (req) => {
        console.log(/* the client IP */);
        return new Response("hello");
    },
    { port: 8080 }
);

是否还有其他方法来防止来自同一设备的多个访问?

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-06 20:18:19

以一种类型安全的方式来完成这个任务有点复杂,因为serve的类型是这样的。首先,我将向您展示一个如何执行该操作的示例,然后我将解释后面的类型。

示例

example.ts

代码语言:javascript
运行
复制
import {
  serve,
  type ConnInfo,
  type Handler,
  type ServeInit,
} from 'https://deno.land/std@0.125.0/http/server.ts';

function assertIsNetAddr (addr: Deno.Addr): asserts addr is Deno.NetAddr {
  if (!['tcp', 'udp'].includes(addr.transport)) {
    throw new Error('Not a network address');
  }
}

function getRemoteAddress (connInfo: ConnInfo): Deno.NetAddr {
  assertIsNetAddr(connInfo.remoteAddr);
  return connInfo.remoteAddr;
}

const handler: Handler = (request, connInfo) => {
  const {hostname, port} = getRemoteAddress(connInfo);
  const message = `You connected from the following address: ${hostname}`;
  return new Response(message);
};

const init: ServeInit = {port: 8080};

serve(handler, init);
console.log(`Listening on port ${init.port}...\nUse ctrl+c to stop`);

类型

查看serve函数的文档,您可以看到它接受两个参数:Handler类型的回调和ServeInit类型的一些选项。

代码语言:javascript
运行
复制
async function serve(handler: Handler, options?: ServeInit): Promise<void>;

Handler回调接受两个参数:一个Request和一个ConnInfo类型的对象。

代码语言:javascript
运行
复制
type Handler = (request: Request, connInfo: ConnInfo) => Response | Promise<Response>;

ConnInfo看起来是这样的:

代码语言:javascript
运行
复制
interface ConnInfo {
  readonly localAddr: Deno.Addr;
  readonly remoteAddr: Deno.Addr;
}

应该具有远程IP地址的部分(从技术上讲,它是远程主机名,但很可能是IP地址,除非您在服务器环境中配置了自定义DNS设置)是connInfo.remoteAddr的对象,它的类型为Deno.Addr,如下所示:

代码语言:javascript
运行
复制
// in the Deno namespace

type Addr = NetAddr | UnixAddr;

--这是它变得复杂的地方。 Deno.Addr是一个歧视结合 of Deno.NetAddrDeno.UnixAddr (这意味着它可能是其中之一),而属性transport用于区分两者。

代码语言:javascript
运行
复制
// in the Deno namespace

interface NetAddr {
  hostname: string;
  port: number;
  transport: "tcp" | "udp";
}

interface UnixAddr {
  path: string;
  transport: "unix" | "unixpacket";
}

net地址具有hostname属性(其值为IP地址)和port属性,而unix地址具有path属性。

监听程序是在内部创建的,用于支持服务器实际上只监听TCP,因此我认为可以安全地假定远程地址将是一个网络地址。但是,由于Handler回调参数在serve函数中的类型签名不显式(尽管应该如此!),所以TypeScript不知道这一点。

所以,在以一种类型安全的方式访问网络地址(而不是unix地址)之前,应该由程序员确保地址实际上是一个净地址。这就是类型断言函数 assertIsNetAddr发挥作用的地方。(类型断言执行运行时测试,从而向编译器提供条件的“保证”:如果条件无法保证,则抛出异常。)因为作为程序员,您已经比TypeScript编译器了解更多(地址在TCP上,并且将是一个网络地址),所以您可以断言该地址确实是一个网络地址。然后编译器将允许您使用该地址作为净地址。

如果您想在地址不是净地址的情况下抛出错误:可以在代码中使用类型谓词作为条件,而不是断言函数。

这里有一个链接到TypeScript游乐场,我在那里创建了一个游乐场,其中包含了示例中使用的类型,这样您就可以探索/实验了。

最后,(,这不是类型安全的)如果您只想在没有检查的情况下使用值(因为您已经完成了您的研究,并且确信您永远不会处理非TCP连接,那么您可以简单地使用类型断言

代码语言:javascript
运行
复制
const handler: Handler = (request, connInfo) => {
  const {hostname, port} = connInfo.remoteAddr as Deno.NetAddr;
  const message = `You connected from the following address: ${hostname}`;
  return new Response(message);
};
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71008150

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档