diff --git a/cli/tests/node_compat/config.json b/cli/tests/node_compat/config.json index 60d5beb344..e77f008761 100644 --- a/cli/tests/node_compat/config.json +++ b/cli/tests/node_compat/config.json @@ -346,6 +346,7 @@ "test-http-agent-getname.js", "test-http-client-get-url.js", "test-http-client-read-in-error.js", + "test-http-localaddress.js", "test-http-outgoing-buffer.js", "test-http-outgoing-internal-headernames-getter.js", "test-http-outgoing-internal-headernames-setter.js", diff --git a/cli/tests/node_compat/test/common/index.js b/cli/tests/node_compat/test/common/index.js index f93f7b7a6b..491dabd2f3 100644 --- a/cli/tests/node_compat/test/common/index.js +++ b/cli/tests/node_compat/test/common/index.js @@ -446,6 +446,9 @@ module.exports = { getArrayBufferViews, getBufferSources, hasCrypto: true, + hasMultiLocalhost() { + return false; + }, invalidArgTypeHelper, mustCall, mustCallAtLeast, diff --git a/cli/tests/node_compat/test/parallel/test-http-localaddress.js b/cli/tests/node_compat/test/parallel/test-http-localaddress.js new file mode 100644 index 0000000000..4d2f6fd9b2 --- /dev/null +++ b/cli/tests/node_compat/test/parallel/test-http-localaddress.js @@ -0,0 +1,64 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 18.12.1 +// This file is automatically generated by "node/_tools/setup.ts". Do not modify this file manually + +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// Flags: --expose-internals +'use strict'; +const common = require('../common'); +if (!common.hasMultiLocalhost()) + common.skip('platform-specific test.'); + +const http = require('http'); +const assert = require('assert'); + +const server = http.createServer((req, res) => { + console.log(`Connect from: ${req.connection.remoteAddress}`); + assert.strictEqual(req.connection.remoteAddress, '127.0.0.2'); + + req.on('end', () => { + res.writeHead(200, { 'Content-Type': 'text/plain' }); + res.end(`You are from: ${req.connection.remoteAddress}`); + }); + req.resume(); +}); + +server.listen(0, '127.0.0.1', () => { + const options = { host: 'localhost', + port: server.address().port, + family: 4, + path: '/', + method: 'GET', + localAddress: '127.0.0.2' }; + + const req = http.request(options, function(res) { + res.on('end', () => { + server.close(); + }); + res.resume(); + }); + req.end(); +}); diff --git a/ext/node/polyfills/http.ts b/ext/node/polyfills/http.ts index 12d71277f0..9104183cac 100644 --- a/ext/node/polyfills/http.ts +++ b/ext/node/polyfills/http.ts @@ -552,8 +552,11 @@ export class IncomingMessageForServer extends NodeReadable { #req: Request; url: string; method: string; + // Polyfills part of net.Socket object. + // These properties are used by `npm:forwarded` for example. + socket: { remoteAddress: string; remotePort: number }; - constructor(req: Request) { + constructor(req: Request, conn: Deno.Conn) { // Check if no body (GET/HEAD/OPTIONS/...) const reader = req.body?.getReader(); super({ @@ -580,6 +583,10 @@ export class IncomingMessageForServer extends NodeReadable { // url: (new URL(request.url).pathname), this.url = req.url?.slice(req.url.indexOf("/", 8)); this.method = req.method; + this.socket = { + remoteAddress: conn.remoteAddr.hostname, + remotePort: conn.remoteAddr.port, + }; this.#req = req; } @@ -601,6 +608,11 @@ export class IncomingMessageForServer extends NodeReadable { this.#req.headers.get("upgrade"), ); } + + // connection is deprecated, but still tested in unit test. + get connection() { + return this.socket; + } } type ServerHandler = ( @@ -669,7 +681,7 @@ class ServerImpl extends EventEmitter { if (reqEvent === null) { break; } - const req = new IncomingMessageForServer(reqEvent.request); + const req = new IncomingMessageForServer(reqEvent.request, tcpConn); if (req.upgrade && this.listenerCount("upgrade") > 0) { const conn = await denoHttp.upgradeHttpRaw( reqEvent.request, diff --git a/tools/node_compat/TODO.md b/tools/node_compat/TODO.md index 2b6338bdce..cd519f439c 100644 --- a/tools/node_compat/TODO.md +++ b/tools/node_compat/TODO.md @@ -3,7 +3,7 @@ NOTE: This file should not be manually edited. Please edit 'cli/tests/node_compat/config.json' and run 'tools/node_compat/setup.ts' instead. -Total: 2924 +Total: 2923 - [abort/test-abort-backtrace.js](https://github.com/nodejs/node/tree/v18.12.1/test/abort/test-abort-backtrace.js) - [abort/test-abort-fatal-error.js](https://github.com/nodejs/node/tree/v18.12.1/test/abort/test-abort-fatal-error.js) @@ -1069,7 +1069,6 @@ Total: 2924 - [parallel/test-http-keepalive-request.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-keepalive-request.js) - [parallel/test-http-listening.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-listening.js) - [parallel/test-http-localaddress-bind-error.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-localaddress-bind-error.js) -- [parallel/test-http-localaddress.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-localaddress.js) - [parallel/test-http-malformed-request.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-malformed-request.js) - [parallel/test-http-many-ended-pipelines.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-many-ended-pipelines.js) - [parallel/test-http-max-header-size-per-stream.js](https://github.com/nodejs/node/tree/v18.12.1/test/parallel/test-http-max-header-size-per-stream.js)