diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs index a363553ba598eb926d004c6eab2461cf7c682d34..ba65686815d52c3fe23d956fdd0521644ff1ffaf 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.Cancellation.cs @@ -195,6 +195,7 @@ public async Task GetAsync_CancelDuringResponseBodyReceived_Buffered_TaskCancele [Theory] [MemberData(nameof(ThreeBools))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/65429", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] public async Task GetAsync_CancelDuringResponseBodyReceived_Unbuffered_TaskCanceledQuickly(bool chunkedTransfer, bool connectionClose, bool readOrCopyToAsync) { if (LoopbackServerFactory.Version >= HttpVersion20.Value && (chunkedTransfer || connectionClose)) diff --git a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs index 48379e2b5055097491275c6260fcee53beac011a..a2775bb9135ae4da652ba4f5ccaa1de119e11a33 100644 --- a/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs +++ b/src/libraries/Common/tests/System/Net/Http/HttpClientHandlerTest.cs @@ -449,8 +449,11 @@ public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() request.Headers.Referrer = new Uri("http://en.wikipedia.org/wiki/Main_Page"); request.Headers.TE.Add(new TransferCodingWithQualityHeaderValue("trailers")); request.Headers.TE.Add(new TransferCodingWithQualityHeaderValue("deflate")); - request.Headers.Trailer.Add("MyTrailer"); - request.Headers.TransferEncoding.Add(new TransferCodingHeaderValue("chunked")); + if (PlatformDetection.IsNotNodeJS) + { + request.Headers.Trailer.Add("MyTrailer"); + request.Headers.TransferEncoding.Add(new TransferCodingHeaderValue("chunked")); + } if (PlatformDetection.IsNotBrowser) { request.Headers.UserAgent.Add(new ProductInfoHeaderValue(new ProductHeaderValue("Mozilla", "5.0"))); @@ -465,8 +468,11 @@ public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() request.Headers.Add("X-Requested-With", "XMLHttpRequest"); request.Headers.Add("DNT", "1 (Do Not Track Enabled)"); request.Headers.Add("X-Forwarded-For", "client1"); - request.Headers.Add("X-Forwarded-For", "proxy1"); - request.Headers.Add("X-Forwarded-For", "proxy2"); + if (PlatformDetection.IsNotNodeJS) + { + request.Headers.Add("X-Forwarded-For", "proxy1"); + request.Headers.Add("X-Forwarded-For", "proxy2"); + } request.Headers.Add("X-Forwarded-Host", "en.wikipedia.org:8080"); request.Headers.Add("X-Forwarded-Proto", "https"); request.Headers.Add("Front-End-Https", "https"); @@ -477,7 +483,10 @@ public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() request.Headers.Add("X-UIDH", "..."); request.Headers.Add("X-Csrf-Token", "i8XNjC4b8KVok4uw5RftR38Wgp2BFwql"); request.Headers.Add("X-Request-ID", "f058ebd6-02f7-4d3f-942e-904344e8cde5"); - request.Headers.Add("X-Request-ID", "f058ebd6-02f7-4d3f-942e-904344e8cde5"); + if (PlatformDetection.IsNotNodeJS) + { + request.Headers.Add("X-Request-ID", "f058ebd6-02f7-4d3f-942e-904344e8cde5"); + } request.Headers.Add("X-Empty", ""); request.Headers.Add("X-Null", (string)null); request.Headers.Add("X-Underscore_Name", "X-Underscore_Name"); @@ -515,7 +524,10 @@ public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() Assert.Equal($"Basic {authSafeValue}", requestData.GetSingleHeaderValue("Proxy-Authorization")); Assert.Equal("Mozilla/5.0", requestData.GetSingleHeaderValue("User-Agent")); Assert.Equal("http://en.wikipedia.org/wiki/Main_Page", requestData.GetSingleHeaderValue("Referer")); - Assert.Equal("MyTrailer", requestData.GetSingleHeaderValue("Trailer")); + if (PlatformDetection.IsNotNodeJS) + { + Assert.Equal("MyTrailer", requestData.GetSingleHeaderValue("Trailer")); + } Assert.Equal("1.0 fred, 1.1 example.com (Apache/1.1)", requestData.GetSingleHeaderValue("Via")); Assert.Equal("1 (Do Not Track Enabled)", requestData.GetSingleHeaderValue("DNT")); } @@ -531,7 +543,15 @@ public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() Assert.Equal("bytes=500-999", requestData.GetSingleHeaderValue("Range")); Assert.Equal("199 - \"Miscellaneous warning\"", requestData.GetSingleHeaderValue("Warning")); Assert.Equal("XMLHttpRequest", requestData.GetSingleHeaderValue("X-Requested-With")); - Assert.Equal("client1, proxy1, proxy2", requestData.GetSingleHeaderValue("X-Forwarded-For")); + if (PlatformDetection.IsNotNodeJS) + { + Assert.Equal("client1, proxy1, proxy2", requestData.GetSingleHeaderValue("X-Forwarded-For")); + } + else + { + // node-fetch polyfill doesn't support combining multiple header values + Assert.Equal("client1", requestData.GetSingleHeaderValue("X-Forwarded-For")); + } Assert.Equal("en.wikipedia.org:8080", requestData.GetSingleHeaderValue("X-Forwarded-Host")); Assert.Equal("https", requestData.GetSingleHeaderValue("X-Forwarded-Proto")); Assert.Equal("https", requestData.GetSingleHeaderValue("Front-End-Https")); @@ -540,7 +560,15 @@ public async Task PostAsync_ManyDifferentRequestHeaders_SentCorrectly() Assert.Equal("http://wap.samsungmobile.com/uaprof/SGH-I777.xml", requestData.GetSingleHeaderValue("X-Wap-Profile")); Assert.Equal("...", requestData.GetSingleHeaderValue("X-UIDH")); Assert.Equal("i8XNjC4b8KVok4uw5RftR38Wgp2BFwql", requestData.GetSingleHeaderValue("X-Csrf-Token")); - Assert.Equal("f058ebd6-02f7-4d3f-942e-904344e8cde5, f058ebd6-02f7-4d3f-942e-904344e8cde5", requestData.GetSingleHeaderValue("X-Request-ID")); + if (PlatformDetection.IsNotNodeJS) + { + Assert.Equal("f058ebd6-02f7-4d3f-942e-904344e8cde5, f058ebd6-02f7-4d3f-942e-904344e8cde5", requestData.GetSingleHeaderValue("X-Request-ID")); + } + else + { + // node-fetch polyfill doesn't support combining multiple header values + Assert.Equal("f058ebd6-02f7-4d3f-942e-904344e8cde5", requestData.GetSingleHeaderValue("X-Request-ID")); + } Assert.Equal("", requestData.GetSingleHeaderValue("X-Null")); Assert.Equal("", requestData.GetSingleHeaderValue("X-Empty")); Assert.Equal("X-Underscore_Name", requestData.GetSingleHeaderValue("X-Underscore_Name")); @@ -938,6 +966,7 @@ public async Task SendAsync_ReadFromSlowStreamingServer_PartialDataReturned() [InlineData(false, true)] [InlineData(false, false)] [InlineData(null, false)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/65429", typeof(PlatformDetection), nameof(PlatformDetection.IsNodeJS))] public async Task ReadAsStreamAsync_HandlerProducesWellBehavedResponseStream(bool? chunked, bool enableWasmStreaming) { if (IsWinHttpHandler && UseVersion >= HttpVersion20.Value) diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index a75f043e09c4a2d1edcc187bae5cb93b3f82920b..492a9e7633727567371d5c09bd8fdce14672d384 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -92,6 +92,8 @@ public static partial class PlatformDetection public static bool IsBrowserDomSupportedOrNotBrowser => IsNotBrowser || IsBrowserDomSupported; public static bool IsNotBrowserDomSupported => !IsBrowserDomSupported; public static bool IsWebSocketSupported => IsEnvironmentVariableTrue("IsWebSocketSupported"); + public static bool IsNodeJS => IsEnvironmentVariableTrue("IsNodeJS"); + public static bool IsNotNodeJS => !IsNodeJS; public static bool LocalEchoServerIsNotAvailable => !LocalEchoServerIsAvailable; public static bool LocalEchoServerIsAvailable => IsBrowser; diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs index f0e58b32ca3456ec87fc18be36e1c2896f304f5a..b3949e548e7ccc62e93907b61de67decb910b67f 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/HttpClientHandlerTest.Http1.cs @@ -16,7 +16,7 @@ public class HttpClientHandlerTest_Http1 : HttpClientHandlerTestBase { public HttpClientHandlerTest_Http1(ITestOutputHelper output) : base(output) { } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNodeJS))] public async Task SendAsync_HostHeader_First() { // RFC 7230 3.2.2. Field Order diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index f8d30de1f7b0d51a99ac4d8ec4430d8a893a45cb..b2ac62db0b4254a366e0a628bb03d148e04bb2f1 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -20,12 +20,35 @@ + WasmTestOnBrowser - $(TestArchiveRoot)browseronly/ + $(TestArchiveRoot)browserornodejs/ $(TestArchiveTestsRoot)$(OSPlatformConfig)/ $(DefineConstants);TARGET_BROWSER + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/package-lock.json b/src/libraries/System.Net.Http/tests/FunctionalTests/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..d16f030e68af62ef3f22ce1a605b873c855d35c7 --- /dev/null +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/package-lock.json @@ -0,0 +1,118 @@ +{ + "name": "system.net.websockets.client.tests", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "system.net.websockets.client.tests", + "dependencies": { + "node-abort-controller": "3.0.1", + "node-fetch": "2.6.7", + "ws": "8.4.0" + } + }, + "node_modules/node-abort-controller": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", + "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" + }, + "node_modules/node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/ws": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", + "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + }, + "dependencies": { + "node-abort-controller": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", + "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==" + }, + "node-fetch": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", + "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "ws": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.4.0.tgz", + "integrity": "sha512-IHVsKe2pjajSUIl4KYMQOdlyliovpEPquKkqbwswulszzI7r0SfQrxnXdWAEqOlDCLrVSJzo+O1hAwdog2sKSQ==", + "requires": {} + } + } +} diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/package.json b/src/libraries/System.Net.Http/tests/FunctionalTests/package.json new file mode 100644 index 0000000000000000000000000000000000000000..d03c34548f36a593d3d5886d5d5959baec053526 --- /dev/null +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/package.json @@ -0,0 +1,9 @@ +{ + "name": "system.net.websockets.client.tests", + "private": true, + "dependencies": { + "node-abort-controller": "3.0.1", + "node-fetch": "2.6.7", + "ws": "8.4.0" + } +} diff --git a/src/mono/wasm/runtime/polyfills.ts b/src/mono/wasm/runtime/polyfills.ts index 048a2477cc0a35f9a7b0ae28c22b7030594ba391..05f12c10453aeb9e114ba9e1da7f590420793d93 100644 --- a/src/mono/wasm/runtime/polyfills.ts +++ b/src/mono/wasm/runtime/polyfills.ts @@ -5,10 +5,7 @@ let node_url: any | undefined = undefined; export async function fetch_like(url: string): Promise { try { - if (typeof (globalThis.fetch) === "function") { - return globalThis.fetch(url, { credentials: "same-origin" }); - } - else if (ENVIRONMENT_IS_NODE) { + if (ENVIRONMENT_IS_NODE) { if (!node_fs) { const node_require = await requirePromise; node_url = node_require("url"); @@ -26,6 +23,9 @@ export async function fetch_like(url: string): Promise { json: () => JSON.parse(arrayBuffer) }; } + else if (typeof (globalThis.fetch) === "function") { + return globalThis.fetch(url, { credentials: "same-origin" }); + } else if (typeof (read) === "function") { // note that it can't open files with unicode names, like Straße.xml // https://bugs.chromium.org/p/v8/issues/detail?id=12541 diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 68a8bb3daee88a04329a2226188059e364b081ee..f0c2329870320689485088e1fda7e80d0d336484 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -316,6 +316,7 @@ function processArguments(incomingArguments) { // cheap way to let the testing infrastructure know we're running in a browser context (or not) setenv["IsBrowserDomSupported"] = is_browser.toString().toLowerCase(); + setenv["IsNodeJS"] = is_node.toString().toLowerCase(); console.log("Application arguments: " + incomingArguments.join(' ')); @@ -360,13 +361,23 @@ if (is_node) { const modulesToLoad = processedArguments.setenv["NPM_MODULES"]; if (modulesToLoad) { modulesToLoad.split(',').forEach(module => { - const parts = module.split(':'); - - let message = `Loading npm '${parts[0]}'`; - const moduleExport = require(parts[0]); - if (parts.length == 2) { - message += ` and attaching to global as '${parts[1]}'.`; - globalThis[parts[1]] = moduleExport; + const { 0:moduleName, 1:globalAlias } = module.split(':'); + + let message = `Loading npm '${moduleName}'`; + let moduleExport = require(moduleName); + + if (globalAlias) { + message += ` and attaching to global as '${globalAlias}'`; + globalThis[globalAlias] = moduleExport; + } else if(moduleName == "node-fetch") { + message += ' and attaching to global'; + globalThis.fetch = moduleExport.default; + globalThis.Headers = moduleExport.Headers; + globalThis.Request = moduleExport.Request; + globalThis.Response = moduleExport.Response; + } else if(moduleName == "node-abort-controller") { + message += ' and attaching to global'; + globalThis.AbortController = moduleExport.AbortController; } console.log(message);