ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Puppeteer HTTPResponse.remoteAddress() 深度解析:读取远端服务器 IP 与端口

Puppeteer HTTPResponse.remoteAddress() 深度解析:读取远端服务器 IP 与端口 Puppeteer HTTPResponse.remoteAddress() 深度解析读取远端服务器 IP 与端口【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer本文围绕 PuppeteerJavaScript API for Chrome and Firefox中HTTPResponse.remoteAddress()方法展开讲解其方法签名、RemoteAddress返回结构、CDP 与 WebDriver BiDi 双协议下的实现差异并结合仓库源码与测试用例给出可直接运行的监控与调试实战示例。读完本文你将掌握如何从一次真实网络响应中取得与远端服务器建立连接的 IP 地址与端口号并理解其在代理、重定向、缓存等边界场景下的取值规律。一、方法概览它返回什么HTTPResponse.remoteAddress()的定义极为简洁——The IP address and port number used to connect to the remote server用于连接远端服务器的 IP 地址与端口号。需要特别强调的是它描述的是当前响应实际与之建立 TCP 连接的远端对端地址而不是 URL 中域名解析出的逻辑地址当请求经由 HTTP 代理转发时它反映的是与代理服务器之间连接的远端地址。方法签名class HTTPResponse { abstract remoteAddress(): RemoteAddress; }该方法的 API 说明位于 puppeteer.httpresponse.remoteaddress.md它是抽象基类HTTPResponse上的抽象方法返回类型为RemoteAddress。其实际子类会根据底层自动化协议CDP 或 WebDriver BiDi给出不同的实现与数据来源下文第三节与第四节会分别拆解。RemoteAddress 返回结构export interface RemoteAddress { ip?: string; port?: number; }接口定义位于 packages/puppeteer-core/src/api/HTTPResponse.ts对应官方文档 puppeteer.remoteaddress.md。两个字段均为可选optionalip远端服务器的 IP 地址字符串可能是 IPv4如127.0.0.1或带括号的 IPv6如[::1]。port远端服务器的端口号数字。字段可选的原因有二其一部分协议如 WebDriver BiDi当前并不暴露该信息实现只能返回占位值其二某些响应如内存缓存命中可能不具备完整的连接元数据。因此消费方代码应对缺失字段做容错处理不要假定ip与port必然存在。二、在哪里获取 HTTPResponse 对象remoteAddress()是HTTPResponse实例上的方法因此获取响应对象是使用前提。常用途径有三导航返回page.goto()、page.reload()等导航方法会 resolve 为导航产生的主响应。import puppeteer from puppeteer; const browser await puppeteer.launch(); const page await browser.newPage(); const response await page.goto(https://example.com); if (response) { console.log(远端地址:, response.remoteAddress()); // 输出示例{ ip: 93.184.215.14, port: 443 } }注意goto()返回的response可能为null——例如跳转到about:blank、data: URL或发生错误页导航时没有可用的 HTTP 响应对象。监听事件订阅page.on(response)可以拿到页面发出的每一个子资源图片、脚本、样式表、XHR/Fetch 等对应的HTTPResponse这是做全站连接审计的入口。page.on(response, response { const {ip, port} response.remoteAddress(); console.log(${response.url()} - ${ip}:${port}); });按条件等待配合page.waitForResponse()精确捕获某个请求的响应。const response await page.waitForResponse(res res.url().includes(/api/data) ); console.log(response.remoteAddress());此外HTTPResponse.request()返回发起该响应的HTTPRequest见 puppeteer.httpresponse.request.md结合request().redirectChain()可以逐跳追溯重定向历史中每一跳的远端地址详见第六节示例。三、CDP 实现数据从哪来在 Chrome/ChromiumCDP 协议路径下响应对象由CdpHTTPResponse实现文件位于 packages/puppeteer-core/src/cdp/HTTPResponse.ts。构造函数接收 DevTools Protocol 的Network.Response负载对应 CDP 的Network.responseReceived事件并从中取出连接元数据this.#remoteAddress { ip: responsePayload.remoteIPAddress, port: responsePayload.remotePort, };remoteIPAddress与remotePort是 CDPNetwork.Response结构体中的字段由浏览器网络栈在收到响应时填充。remoteAddress()的 getter 只是直接返回这个缓存的快照override remoteAddress(): RemoteAddress { return this.#remoteAddress; }也就是说该地址在构造响应对象那一刻就已固定之后不会随连接状态变化而更新属于一次性快照数据。这一点与securityDetails()返回 TLS/HTTPS 安全连接详情见 puppeteer.httpresponse.securitydetails.md互补前者回答连到哪台服务器后者回答连接是否加密、证书归属。在 packages/puppeteer-core/src/cdp/NetworkManager.ts 附近可以找到CdpHTTPResponse被组装的位置它接收来自 CDP 事件流的响应负载与 extraInfo 事件单测 packages/puppeteer-core/src/cdp/HTTPResponse.test.ts 中构造CdpHTTPResponse时亦使用remoteIPAddress: 127.0.0.1、remotePort: 80这类负载字段印证了数据源结构。四、WebDriver BiDi 实现协议缺口的占位值Firefox 及使用 WebDriver BiDi 协议连接的浏览器走BidiHTTPResponse实现文件位于 packages/puppeteer-core/src/bidi/HTTPResponse.ts。由于 WebDriver BiDi 标准目前没有提供远端地址的等价字段该实现对remoteAddress()返回固定的占位值invokeAtMostOnceForArguments override remoteAddress(): RemoteAddress { return { ip: , port: -1, }; }这里有两个值得注意的细节占位值约定ip为空字符串、port为-1语义上即未知/不可用。跨浏览器编写代码时应通过判断port -1 || !ip来识别 BiDi 场景下的无效数据而不是直接信任返回值。协议差距在测试中被固化仓库的 test/TestExpectations.json 中明确登记了一条针对webDriverBiDi参数组合的期望{ testIdPattern: [network.test] network Response.remoteAddress *, platforms: [darwin, linux, win32], parameters: [webDriverBiDi], expectations: [FAIL], comment: Bidi does not have equivalent field }注释直接写明Bidi does not have equivalent field——即该用例在 BiDi 模式下被标记为预期失败FAIL这正是协议能力差异在官方测试矩阵中的显式表达。因此若你的自动化脚本需要强依赖远端地址信息例如做安全审计、代理校验、合规取证当前应优先使用 Chrome/Chromium CDP 的组合如需覆盖 Firefox则应把该能力视作尽力而为。五、真实调用链与测试用例佐证官方集成测试位于 test/src/network.test.ts 的Response.remoteAddress分组两个用例直接验证了上文描述的语义用例一基础取值should workconst response (await page.goto(server.EMPTY_PAGE))!; const remoteAddress response.remoteAddress(); // Either IPv6 or IPv4, depending on environment. expect( remoteAddress.ip!.includes(::1) || remoteAddress.ip 127.0.0.1, ).toBe(true); expect(remoteAddress.port).toBe(server.PORT);测试注释揭示了关键约束返回的 IP 格式取决于环境——在启用 IPv6 回环的环境下为::1否则为 IPv4 的127.0.0.1而端口必须精确等于本地测试服务器的监听端口。这提醒我们在断言远端地址时不要硬编码某一种 IP 字面量而应允许 IPv4/IPv6 两种形态判断时可以用includes/正则等宽松方式。用例二重定向场景should support redirectsserver.setRedirect(/foo.html, /empty.html); const response (await page.goto(FOO_URL))!; const redirectChain response.request().redirectChain(); expect(redirectChain).toHaveLength(1); expect(redirectChain[0]!.response()!.remoteAddress().port).toBe(server.PORT);该用例表明重定向链上每一跳的中间响应都各自持有独立的HTTPResponse通过request().redirectChain()获取并且每一跳都可以单独调用remoteAddress()查询其远端地址。六、实战连接审计与边界防护场景一监测页面实际连接了哪些主机下面把监听、导航与地址提取组合起来实现一个连接目的地审计器可用于发现页面是否偷偷连向了预期之外的服务器import puppeteer from puppeteer; const browser await puppeteer.launch(); const page await browser.newPage(); const destinations new Mapstring, string(); page.on(response, response { const {ip, port} response.remoteAddress(); if (ip) { // 同一 URL 可能命中缓存/多次请求用 URL 作为键覆盖记录 destinations.set(response.url(), ${ip}:${port}); } }); await page.goto(https://example.com, {waitUntil: networkidle0}); for (const [url, addr] of destinations) { console.log(${url} - ${addr}); } await browser.close();场景二识别来自代理的真实对端remoteAddress()反映的是 TCP 连接的真实对端。若 Chrome 通过--proxy-server走代理访问目标站返回的ip:port通常是代理服务器而非目标站地址对比 URL 主机名与返回 IP 是否一致即可判断流量是否经过代理转发。场景三区分缓存命中与网络请求HTTPResponse还提供了fromCache()是否来自浏览器磁盘/内存缓存与fromServiceWorker()是否由 Service Worker 响应等方法。将remoteAddress()与这两者结合可以判断凡是真正走了网络连接的响应才具备有意义的远端地址而缓存或 Service Worker 直接返回的响应其连接元数据往往不完整或已无实际意义解读时应降低对remoteAddress()的权重。场景四跨浏览器适配写法由于 BiDi 返回{ip: , port: -1}推荐封装一个统一访问函数function describeRemoteAddress(remoteAddress: {ip?: string; port?: number}) { if (!remoteAddress.ip || remoteAddress.port -1) { return unavailable (protocol does not expose remote address); } return ${remoteAddress.ip}:${remoteAddress.port}; }七、易混淆点与边界小结与 DNS 结果的差别remoteAddress()返回连接对端地址若启用代理或负载均衡可能与 URL 域名直接解析出的 IP 不一致这是正常现象。IPv4 / IPv6 形态差异同一站点在不同网络环境下可能返回1.2.3.4或[::1]等不同格式断言与日志输出需兼容。重定向链逐跳可取每一跳都有独立的HTTPResponse可借助request().redirectChain()分别读取见上文测试用例二。跨协议可用性不同CDP 提供真实地址WebDriver BiDi 返回占位值ip: 、port: -1且官方测试矩阵中该能力在 BiDi 参数下被标记为预期失败。与securityDetails()互补需要 TLS 证书信息签发者、有效期、SAN 等时调用securityDetails()HTTP 明文场景下该方法返回null。总结HTTPResponse.remoteAddress()是一把轻量但信息量很大的连接探针在 CDP 路径下它基于Network.Response的remoteIPAddress/remotePort字段返回 TCP 连接真实对端在 WebDriver BiDi 路径下受协议限制仅返回占位值。理解其数据来源与协议差异后你可以将它用于请求来源审计、代理行为验证、缓存判定辅助以及重定向链分析与HTTPResponse家族的url()、headers()、securityDetails()、fromCache()等方法配合即可构建完整的响应级网络观测视图。如需查看更多相关 API 定义可继续阅读 HTTPResponse 类总览 与 RemoteAddress 接口。【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表