From df668017eebf98f8d724177d220712c0e6218114 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Fri, 9 Nov 2018 15:29:00 -0800 Subject: [PATCH 1/4] Add HTTPS tests for node/browser tests (#3283) --- build/dependencies.props | 96 +++++++++--------- clients/ts/FunctionalTests/Program.cs | 40 +++++++- .../scripts/karma.local.conf.js | 3 +- .../ts/FunctionalTests/scripts/run-tests.ts | 40 +++++--- clients/ts/FunctionalTests/testCert.pfx | Bin 0 -> 2483 bytes clients/ts/FunctionalTests/testCertECC.pfx | Bin 0 -> 1403 bytes clients/ts/FunctionalTests/ts/Common.ts | 16 ++- .../FunctionalTests/ts/HubConnectionTests.ts | 32 +++++- 8 files changed, 158 insertions(+), 69 deletions(-) create mode 100644 clients/ts/FunctionalTests/testCert.pfx create mode 100644 clients/ts/FunctionalTests/testCertECC.pfx diff --git a/build/dependencies.props b/build/dependencies.props index 1dd1f2c38f..361fce7a5f 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,58 +5,58 @@ 0.10.13 3.1.0 - 2.2.0-rtm-35532 + 2.2.0-rtm-181106-13 2.2.0-preview2-20181011.2 1.7.3.4 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-35661 2.2.0-preview3-35457 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-35661 4.5.0 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-rtm-35532 - 2.2.0-preview3-27014-02 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-35661 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-181106-13 + 2.2.0-rtm-27105-02 15.6.1 4.10.0 2.0.3 diff --git a/clients/ts/FunctionalTests/Program.cs b/clients/ts/FunctionalTests/Program.cs index 0a95291396..a762f99e55 100644 --- a/clients/ts/FunctionalTests/Program.cs +++ b/clients/ts/FunctionalTests/Program.cs @@ -3,8 +3,11 @@ using System; using System.IO; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Win32; namespace FunctionalTests { @@ -31,7 +34,42 @@ namespace FunctionalTests factory.AddDebug(); factory.SetMinimumLevel(LogLevel.Information); }) - .UseKestrel() + .UseKestrel((builderContext, options) => + { + options.ConfigureHttpsDefaults(httpsOptions => + { + bool useRSA = false; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Detect Win10+ + var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion"); + var major = key.GetValue("CurrentMajorVersionNumber") as int?; + var minor = key.GetValue("CurrentMinorVersionNumber") as int?; + + if (major.HasValue && minor.HasValue) + { + useRSA = true; + } + } + else + { + useRSA = true; + } + + if (useRSA) + { + // RSA cert, won't work on Windows 8.1 & Windows 2012 R2 using HTTP2, and ECC won't work in some Node environments + var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCert.pfx"); + httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); + } + else + { + // ECC cert, works on Windows 8.1 & Windows 2012 R2 using HTTP2 + var certPath = Path.Combine(Directory.GetCurrentDirectory(), "testCertECC.pfx"); + httpsOptions.ServerCertificate = new X509Certificate2(certPath, "testPassword"); + } + }); + }) .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup(); diff --git a/clients/ts/FunctionalTests/scripts/karma.local.conf.js b/clients/ts/FunctionalTests/scripts/karma.local.conf.js index 3c127435b9..fdcb9b779b 100644 --- a/clients/ts/FunctionalTests/scripts/karma.local.conf.js +++ b/clients/ts/FunctionalTests/scripts/karma.local.conf.js @@ -57,8 +57,9 @@ try { ChromeHeadlessNoSandbox: { base: 'ChromeHeadless', + // Ignore cert errors to allow our test cert to work (NEVER do this outside of testing) // ChromeHeadless runs about 10x slower on Windows 7 machines without the --proxy switches below. Why? ¯\_(ツ)_/¯ - flags: ["--no-sandbox", "--proxy-server='direct://'", "--proxy-bypass-list=*"] + flags: ["--no-sandbox", "--proxy-server='direct://'", "--proxy-bypass-list=*", "--allow-insecure-localhost", "--ignore-certificate-errors"] } }, }); diff --git a/clients/ts/FunctionalTests/scripts/run-tests.ts b/clients/ts/FunctionalTests/scripts/run-tests.ts index 3fcda8945a..7dd600eded 100644 --- a/clients/ts/FunctionalTests/scripts/run-tests.ts +++ b/clients/ts/FunctionalTests/scripts/run-tests.ts @@ -33,11 +33,12 @@ setTimeout(() => { process.exit(1); }, 1000 * 60 * 10); -function waitForMatch(command: string, process: ChildProcess, regex: RegExp): Promise { - return new Promise((resolve, reject) => { +function waitForMatches(command: string, process: ChildProcess, regex: RegExp, matchCount: number): Promise { + return new Promise((resolve, reject) => { const commandDebug = _debug(`${command}`); try { let lastLine = ""; + let results: string[] = null; async function onData(this: Readable, chunk: string | Buffer): Promise { try { @@ -50,15 +51,23 @@ function waitForMatch(command: string, process: ChildProcess, regex: RegExp): Pr lastLine = ""; chunk = chunk.substring(lineEnd + EOL.length); + const res = regex.exec(chunkLine); + if (results == null && res != null) { + results = res; + } else if (res != null) { + results = Array().concat(results, res); + } - const results = regex.exec(chunkLine); - commandDebug(chunkLine); - if (results && results.length > 0) { + // * 2 because each match will have the original line plus the match + if (results && results.length >= matchCount * 2) { resolve(results); return; } + + commandDebug(chunkLine); lineEnd = chunk.indexOf(EOL); } + lastLine = chunk.toString(); } catch (e) { this.removeAllListeners("data"); @@ -158,15 +167,17 @@ function runKarma(karmaConfig) { }); } -function runJest(url: string) { +function runJest(httpsUrl: string, httpUrl: string) { const jestPath = path.resolve(__dirname, "..", "..", "common", "node_modules", "jest", "bin", "jest.js"); const configPath = path.resolve(__dirname, "..", "func.jest.config.js"); console.log("Starting Node tests using Jest."); return new Promise((resolve, reject) => { const logStream = fs.createWriteStream(path.resolve(__dirname, "..", "..", "..", "..", "artifacts", "logs", "node.functionaltests.log")); - const p = exec(`"${process.execPath}" "${jestPath}" --config "${configPath}"`, { env: { SERVER_URL: url }, timeout: 200000, maxBuffer: 10 * 1024 * 1024 }, + // Use NODE_TLS_REJECT_UNAUTHORIZED to allow our test cert to be used by the Node tests (NEVER use this environment variable outside of testing) + const p = exec(`"${process.execPath}" "${jestPath}" --config "${configPath}"`, { env: { SERVER_URL: `${httpsUrl};${httpUrl}`, NODE_TLS_REJECT_UNAUTHORIZED: 0 }, timeout: 200000, maxBuffer: 10 * 1024 * 1024 }, (error: any, stdout, stderr) => { + console.log("Finished Node tests."); if (error) { console.log(error.message); return resolve(error.code); @@ -183,7 +194,7 @@ function runJest(url: string) { const serverPath = path.resolve(__dirname, "..", "bin", configuration, "netcoreapp2.2", "FunctionalTests.dll"); debug(`Launching Functional Test Server: ${serverPath}`); - let desiredServerUrl = "http://127.0.0.1:0"; + let desiredServerUrl = "https://127.0.0.1:0;http://127.0.0.1:0"; if (sauce) { // SauceLabs can only proxy certain ports for Edge and Safari. @@ -212,11 +223,12 @@ function runJest(url: string) { process.on("exit", cleanup); debug("Waiting for Functional Test Server to start"); - const matches = await waitForMatch("dotnet", dotnet, /Now listening on: (http:\/\/[^\/]+:[\d]+)/); - const url = matches[1]; - debug(`Functional Test Server has started at ${url}`); + const matches = await waitForMatches("dotnet", dotnet, /Now listening on: (https?:\/\/[^\/]+:[\d]+)/, 2); + const httpsUrl = matches[1]; + const httpUrl = matches[3]; + debug(`Functional Test Server has started at ${httpsUrl} and ${httpUrl}`); - debug(`Using SignalR Server: ${url}`); + debug(`Using SignalR Server: ${httpsUrl} and ${httpUrl}`); // Start karma server const conf = { @@ -238,9 +250,9 @@ function runJest(url: string) { } // Pass server URL to tests - conf.client.args = ["--server", url]; + conf.client.args = ["--server", `${httpsUrl};${httpUrl}`]; - const jestExit = await runJest(url); + const jestExit = await runJest(httpsUrl, httpUrl); // Check if we got any browsers let karmaExit; diff --git a/clients/ts/FunctionalTests/testCert.pfx b/clients/ts/FunctionalTests/testCert.pfx new file mode 100644 index 0000000000000000000000000000000000000000..7118908c2d730670c16e9f8b2c532a262c951989 GIT binary patch literal 2483 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 literal 0 HcmV?d00001 diff --git a/clients/ts/FunctionalTests/testCertECC.pfx b/clients/ts/FunctionalTests/testCertECC.pfx new file mode 100644 index 0000000000000000000000000000000000000000..888ccb032a97ac6d36afdf569ea5a7ddb15d1111 GIT binary patch literal 1403 zcmXqLVl8K4WHxAGHD=?~YV&CO&dbQoxS)wug{6sA0VphE(8Tx`MT+qqOB3TOpzt#w ze#FKN)y2cb$h4sGk3r*40~t0hm>|$-J{FGUht3{YZd@71#KeAqrSZm11(&cnPAfwl zX1aFU|ILVKRdSQy- z2e!P4PsNH>x|lM#?2tN^u!OtsfyA#vHJ9&i(-)s?)TWnwcKOj)d$0B8{MztM`n%q| z{M9mBORWq;!#mbWatr7EcMEIZ*4a?}=x6n>tpRI(B{{?~YMHHDZ=^4pw$LMjck7I! zzvaINOS^^Uruf~=&E8?7V|LlUW|HCQxevMbf3gl*&Zjy5$@e5btT;st*;rT@85kH0ViAHOh5>SZ3?&Sy47v;k43-Qj4CX-E zj3J334JeYzV8UR^U<_oLFc>i;G9&|8mO$DVES3mlr2y5X0c9WqN8QWz3J#%r@N zvM@H83o?R@_hrZgYAs^OXD9~ZG@x|~48c%VInarMD*}qAgT({D zI?I4&qyYIv22IT3aQCybEofrq01B}%F)|o5F(D@n%y|D%?IOCx)9)xK-W!^jE<{h@ zzRS8(=PhHipURGk)u%p0dmpSmyuxYW{=ZK;@@v;tW*6QvI&pvUzn#nCmEG+(*OaEY zHxyaA$}FzmBM{?rk!9XSmC#1RXUU6B9DMJ%;BbQNIu(-%91(Bi1(NdJtYiL`@IGhA zymKkomSs`&Uz4m!k3&o!JUAh?!Q#QD&0np^X~?&+OfDO}h40Y?O!j zm+pF&LXT;0D;CUJ{}3h zV=+TtLHRF*V;_PYSBA>=_B;HRT5ZqPx~O3B#ecWfUQ`N+{Z zHz=;g;q`anh}wB4zjfZ3E4-jitMBI#j_b+4d0NjkdpS5x{qcHna;er`w{2xzHP5Zr zD&3qSZl%|@=-sy&?CeTA)jc}0p9EZ5|Fin@5x#gvcCPO70Noeu z@wbEw&a=P1_dH|K#j4X&B#)n*m$*J9S&DJz`WYV`w#1pbC5ZgotXi%3+&@ji$iH2g zv4S=Abj$Qi?LQ|je3Ll1)vhhMB<0@21zEE$lmu>lRDDD5pW^)NA7`h3_PLk6;-sH% zm%OvjeamWTnc45;N{7w|~ZryW7oH-#!yqnq&3MUig`wfZDsXX`GjNc&tH zTox#|;gN~NB(75l+b115bTNbVf=qjk$Bf-)P0FshsX8@Gx+^DLdwhjTxV_?1HaFF6 zk|m#OWi>>ab5q>se9O>3d-2GAkLS@>eRgCh7+4#~8?dvnYV$EONwJ8uv-NfrpVt4B r?jsp}XX2cX|BhL`WD&_^IHf-$@%m29k1q?q&7B#jKP_$tC_?}MhAKx! literal 0 HcmV?d00001 diff --git a/clients/ts/FunctionalTests/ts/Common.ts b/clients/ts/FunctionalTests/ts/Common.ts index 13062d97de..37b9b532fb 100644 --- a/clients/ts/FunctionalTests/ts/Common.ts +++ b/clients/ts/FunctionalTests/ts/Common.ts @@ -5,27 +5,35 @@ import { HttpTransportType, IHubProtocol, JsonHubProtocol } from "@aspnet/signal import { MessagePackHubProtocol } from "@aspnet/signalr-protocol-msgpack"; export let ENDPOINT_BASE_URL: string; +export let ENDPOINT_BASE_HTTPS_URL: string; if (typeof window !== "undefined" && (window as any).__karma__) { const args = (window as any).__karma__.config.args as string[]; - let server = ""; + let httpsServer = ""; + let httpServer = ""; for (let i = 0; i < args.length; i += 1) { switch (args[i]) { case "--server": i += 1; - server = args[i]; + const urls = args[i].split(";"); + httpsServer = urls[0]; + httpServer = urls[1]; + console.log(httpServer); break; } } // Running in Karma? Need to use an absolute URL - ENDPOINT_BASE_URL = server; + ENDPOINT_BASE_URL = httpServer; + ENDPOINT_BASE_HTTPS_URL = httpsServer; console.log(`Using SignalR Server: ${ENDPOINT_BASE_URL}`); } else if (typeof document !== "undefined") { ENDPOINT_BASE_URL = `${document.location.protocol}//${document.location.host}`; } else if (process && process.env && process.env.SERVER_URL) { - ENDPOINT_BASE_URL = process.env.SERVER_URL; + const urls = process.env.SERVER_URL.split(";"); + ENDPOINT_BASE_HTTPS_URL = urls[0]; + ENDPOINT_BASE_URL = urls[1]; } else { throw new Error("The server could not be found."); } diff --git a/clients/ts/FunctionalTests/ts/HubConnectionTests.ts b/clients/ts/FunctionalTests/ts/HubConnectionTests.ts index 8d54c23884..b7665cb306 100644 --- a/clients/ts/FunctionalTests/ts/HubConnectionTests.ts +++ b/clients/ts/FunctionalTests/ts/HubConnectionTests.ts @@ -7,11 +7,12 @@ import { AbortError, DefaultHttpClient, HttpClient, HttpRequest, HttpResponse, HttpTransportType, HubConnectionBuilder, IHttpConnectionOptions, JsonHubProtocol, NullLogger } from "@aspnet/signalr"; import { MessagePackHubProtocol } from "@aspnet/signalr-protocol-msgpack"; -import { eachTransport, eachTransportAndProtocol, ENDPOINT_BASE_URL } from "./Common"; +import { eachTransport, eachTransportAndProtocol, ENDPOINT_BASE_HTTPS_URL, ENDPOINT_BASE_URL } from "./Common"; import "./LogBannerReporter"; import { TestLogger } from "./TestLogger"; const TESTHUBENDPOINT_URL = ENDPOINT_BASE_URL + "/testhub"; +const TESTHUBENDPOINT_HTTPS_URL = ENDPOINT_BASE_HTTPS_URL + "/testhub"; const TESTHUB_NOWEBSOCKETS_ENDPOINT_URL = ENDPOINT_BASE_URL + "/testhub-nowebsockets"; // On slower CI machines, these tests sometimes take longer than 5s @@ -62,6 +63,35 @@ describe("hubConnection", () => { }); }); + // Run test in Node or Chrome, but not on macOS + if ((process && process.platform !== "darwin") && (typeof navigator === "undefined" || navigator.userAgent.search("Chrome") !== -1)) { + it("using https, can invoke server method and receive result", (done) => { + const message = "你好,世界!"; + + const hubConnection = getConnectionBuilder(transportType, TESTHUBENDPOINT_HTTPS_URL) + .withHubProtocol(protocol) + .build(); + + hubConnection.onclose((error) => { + expect(error).toBeUndefined(); + done(); + }); + + hubConnection.start().then(() => { + hubConnection.invoke("Echo", message).then((result) => { + expect(result).toBe(message); + }).catch((e) => { + fail(e); + }).then(() => { + hubConnection.stop(); + }); + }).catch((e) => { + fail(e); + done(); + }); + }); + } + it("can invoke server method non-blocking and not receive result", (done) => { const message = "你好,世界!"; From a242dc726d714e0a10ed423e1e526e8902b0fc2c Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 11 Nov 2018 16:31:08 -0800 Subject: [PATCH 2/4] Ensure .jar files are included in code signing with the correct certificate --- build/repo.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/repo.targets b/build/repo.targets index c246ce275a..66065ac2a1 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -75,7 +75,7 @@ - + JavaJar @@ -88,7 +88,7 @@ ship - + From a9def470e3b8e1480c55d1c311e4b37472140307 Mon Sep 17 00:00:00 2001 From: Nate McMaster Date: Sun, 11 Nov 2018 20:24:25 -0800 Subject: [PATCH 3/4] Don't attempt to detect java if SkipJavaClient is true --- build/repo.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build/repo.targets b/build/repo.targets index 66065ac2a1..6cdce57f88 100644 --- a/build/repo.targets +++ b/build/repo.targets @@ -75,8 +75,8 @@ - - + + JavaJar $(JavaClientVersion) From b476df9acd22a403d9fe46ecb0feedf052035e39 Mon Sep 17 00:00:00 2001 From: BrennanConroy Date: Mon, 12 Nov 2018 09:06:51 -0800 Subject: [PATCH 4/4] Custom CORS-like middleware to allow wildcard origin in test app (#3292) --- .../ts/FunctionalTests/FunctionalTests.csproj | 1 - clients/ts/FunctionalTests/Startup.cs | 52 ++++++++++++++----- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/clients/ts/FunctionalTests/FunctionalTests.csproj b/clients/ts/FunctionalTests/FunctionalTests.csproj index 2de14a67d6..06948653fc 100644 --- a/clients/ts/FunctionalTests/FunctionalTests.csproj +++ b/clients/ts/FunctionalTests/FunctionalTests.csproj @@ -26,7 +26,6 @@ - diff --git a/clients/ts/FunctionalTests/Startup.cs b/clients/ts/FunctionalTests/Startup.cs index 975de64581..5417be9d64 100644 --- a/clients/ts/FunctionalTests/Startup.cs +++ b/clients/ts/FunctionalTests/Startup.cs @@ -13,7 +13,9 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Connections; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Primitives; using Microsoft.IdentityModel.Tokens; +using Microsoft.Net.Http.Headers; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; @@ -32,15 +34,13 @@ namespace FunctionalTests { options.EnableDetailedErrors = true; }) - .AddJsonProtocol(options => - { - // we are running the same tests with JSON and MsgPack protocols and having - // consistent casing makes it cleaner to verify results - options.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver(); - }) - .AddMessagePackProtocol(); - - services.AddCors(); + .AddJsonProtocol(options => + { + // we are running the same tests with JSON and MsgPack protocols and having + // consistent casing makes it cleaner to verify results + options.PayloadSerializerSettings.ContractResolver = new DefaultContractResolver(); + }) + .AddMessagePackProtocol(); services.AddAuthorization(options => { @@ -90,12 +90,36 @@ namespace FunctionalTests app.UseFileServer(); - app.UseCors(policyBuilder => + // Custom CORS to allow any origin + credentials (which isn't allowed by the CORS spec) + // This is for testing purposes only (karma hosts the client on its own server), never do this in production + app.Use((context, next) => { - policyBuilder.AllowAnyOrigin() - .AllowAnyHeader() - .AllowAnyMethod() - .AllowCredentials(); + var originHeader = context.Request.Headers[HeaderNames.Origin]; + if (!StringValues.IsNullOrEmpty(originHeader)) + { + context.Response.Headers[HeaderNames.AccessControlAllowOrigin] = originHeader; + context.Response.Headers[HeaderNames.AccessControlAllowCredentials] = "true"; + + var requestMethod = context.Request.Headers[HeaderNames.AccessControlRequestMethod]; + if (!StringValues.IsNullOrEmpty(requestMethod)) + { + context.Response.Headers[HeaderNames.AccessControlAllowMethods] = requestMethod; + } + + var requestHeaders = context.Request.Headers[HeaderNames.AccessControlRequestHeaders]; + if (!StringValues.IsNullOrEmpty(requestHeaders)) + { + context.Response.Headers[HeaderNames.AccessControlAllowHeaders] = requestHeaders; + } + } + + if (string.Equals(context.Request.Method, "OPTIONS", StringComparison.OrdinalIgnoreCase)) + { + context.Response.StatusCode = StatusCodes.Status204NoContent; + return Task.CompletedTask; + } + + return next.Invoke(); }); app.UseConnections(routes =>