[CORS] Remove E2E functional tests (#13826)
* The tests are low value. * The tests are flaky. * The tests cover mostly browser behavior not spec compliance. * It's an area that doesn't change often. * We have unit tests to cover the casuistic.
This commit is contained in:
parent
82a41f0dac
commit
2cae0cd451
|
|
@ -1,45 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text;
|
||||
using Xunit.Sdk;
|
||||
|
||||
namespace FunctionalTests
|
||||
{
|
||||
public class Assert : Xunit.Assert
|
||||
{
|
||||
public static void Success(in ProcessResult processResult)
|
||||
{
|
||||
if (processResult.ExitCode != 0)
|
||||
{
|
||||
throw new ProcessAssertException(processResult);
|
||||
}
|
||||
}
|
||||
|
||||
private class ProcessAssertException : XunitException
|
||||
{
|
||||
public ProcessAssertException(in ProcessResult processResult)
|
||||
{
|
||||
Result = processResult;
|
||||
}
|
||||
|
||||
public ProcessResult Result { get; }
|
||||
|
||||
public override string Message
|
||||
{
|
||||
get
|
||||
{
|
||||
var message = new StringBuilder();
|
||||
message.Append(Result.ProcessStartInfo.FileName);
|
||||
message.Append(" ");
|
||||
message.Append(Result.ProcessStartInfo.Arguments);
|
||||
message.Append($" exited with {Result.ExitCode}.");
|
||||
message.AppendLine();
|
||||
message.AppendLine();
|
||||
message.Append(Result.Output);
|
||||
return message.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TestGroupName>Cors.FunctionalTests</TestGroupName>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);node_modules\**\*</DefaultItemExcludes>
|
||||
|
||||
<!-- Tests do not work on Helix or when bin/ directory is not in project directory due to undeclared dependency on test content. -->
|
||||
<!-- https://github.com/aspnet/AspNetCore/issues/7990 -->
|
||||
<BuildHelixPayload>false</BuildHelixPayload>
|
||||
<BaseOutputPath />
|
||||
<OutputPath />
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- We don't need anything in this assembly, we just want to make sure it's built -->
|
||||
<ProjectReference Include="$(RepoRoot)src\Hosting\Server.IntegrationTesting\src\Microsoft.AspNetCore.Server.IntegrationTesting.csproj" />
|
||||
<ProjectReference Include="..\testassets\TestOrigin\TestOrigin.csproj">
|
||||
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\testassets\TestDestination\TestDestination.csproj">
|
||||
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\testassets\CorsMiddlewareWebSite\CorsMiddlewareWebSite.csproj">
|
||||
<ReferenceOutputAssembly>False</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.Extensions.Logging.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
<Project>
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.props))\Directory.Build.props" />
|
||||
|
||||
<!--
|
||||
This project file is present so the CI will run `yarn install` on the package.json file.
|
||||
The C# invokes node to start the tests.
|
||||
-->
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsBuildable>false</IsBuildable>
|
||||
<IsTestProject>false</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.targets))\Directory.Build.targets" />
|
||||
</Project>
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Server.IntegrationTesting;
|
||||
using Microsoft.AspNetCore.Testing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Testing;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
[assembly: CollectionBehavior(CollectionBehavior.CollectionPerAssembly)]
|
||||
|
||||
namespace FunctionalTests
|
||||
{
|
||||
public class CorsMiddlewareFunctionalTests : LoggedTest
|
||||
{
|
||||
public CorsMiddlewareFunctionalTests(ITestOutputHelper output)
|
||||
: base(output)
|
||||
{
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public ITestOutputHelper Output { get; }
|
||||
|
||||
[Flaky("https://github.com/aspnet/aspnetcore-internal/issues/2865", FlakyOn.All)]
|
||||
[ConditionalTheory]
|
||||
[OSSkipCondition(OperatingSystems.MacOSX, SkipReason = "Disabling this test on OSX until we have a resolution for https://github.com/aspnet/AspNetCore-Internal/issues/1619")]
|
||||
[InlineData("Startup")]
|
||||
[InlineData("StartupWithoutEndpointRouting")]
|
||||
public async Task RunClientTests(string startup)
|
||||
{
|
||||
using (StartLog(out var loggerFactory))
|
||||
using (var deploymentResult = await CreateDeployments(loggerFactory, startup))
|
||||
{
|
||||
ProcessStartInfo processStartInfo;
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "cmd",
|
||||
Arguments = "/c npm test --no-color --no-watchman",
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
processStartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = "npm",
|
||||
Arguments = "test --no-watchman",
|
||||
};
|
||||
}
|
||||
// Disallow the test from downloading \ installing chromium.
|
||||
processStartInfo.Environment["PUPPETEER_SKIP_CHROMIUM_DOWNLOAD"] = "true";
|
||||
processStartInfo.Environment["DESTINATION_PORT"] = deploymentResult.DestinationResult.HttpClient.BaseAddress.Port.ToString();
|
||||
processStartInfo.Environment["ORIGIN_PORT"] = deploymentResult.OriginResult.HttpClient.BaseAddress.Port.ToString();
|
||||
processStartInfo.Environment["SECOND_ORIGIN_PORT"] = deploymentResult.SecondOriginResult.HttpClient.BaseAddress.Port.ToString();
|
||||
|
||||
// Act
|
||||
var result = await ProcessManager.RunProcessAsync(processStartInfo, loggerFactory.CreateLogger("ProcessManager"));
|
||||
|
||||
// Assert
|
||||
Assert.Success(result);
|
||||
Assert.Contains("Test Suites: 1 passed, 1 total", result.Output);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<CorsDeploymentResult> CreateDeployments(ILoggerFactory loggerFactory, string startup)
|
||||
{
|
||||
// https://github.com/aspnet/AspNetCore/issues/7990
|
||||
#pragma warning disable 0618
|
||||
var solutionPath = TestPathUtilities.GetSolutionRootDirectory("Middleware");
|
||||
#pragma warning restore 0618
|
||||
|
||||
var configuration =
|
||||
#if RELEASE
|
||||
"Release";
|
||||
#else
|
||||
"Debug";
|
||||
#endif
|
||||
|
||||
var originParameters = new DeploymentParameters
|
||||
{
|
||||
TargetFramework = "netcoreapp3.0",
|
||||
RuntimeFlavor = RuntimeFlavor.CoreClr,
|
||||
ServerType = ServerType.Kestrel,
|
||||
ApplicationPath = Path.Combine(solutionPath, "CORS", "test", "testassets", "TestOrigin"),
|
||||
PublishApplicationBeforeDeployment = false,
|
||||
ApplicationType = ApplicationType.Portable,
|
||||
Configuration = configuration,
|
||||
};
|
||||
|
||||
var originFactory = ApplicationDeployerFactory.Create(originParameters, loggerFactory);
|
||||
var originDeployment = await originFactory.DeployAsync();
|
||||
|
||||
var secondOriginFactory = ApplicationDeployerFactory.Create(originParameters, loggerFactory);
|
||||
var secondOriginDeployment = await secondOriginFactory.DeployAsync();
|
||||
|
||||
var port = originDeployment.HttpClient.BaseAddress.Port;
|
||||
var destinationParameters = new DeploymentParameters
|
||||
{
|
||||
TargetFramework = "netcoreapp3.0",
|
||||
RuntimeFlavor = RuntimeFlavor.CoreClr,
|
||||
ServerType = ServerType.Kestrel,
|
||||
ApplicationPath = Path.Combine(solutionPath, "CORS", "test", "testassets", "TestDestination"),
|
||||
PublishApplicationBeforeDeployment = false,
|
||||
ApplicationType = ApplicationType.Portable,
|
||||
Configuration = configuration,
|
||||
EnvironmentVariables =
|
||||
{
|
||||
["CORS_STARTUP"] = startup,
|
||||
["ORIGIN_PORT"] = port.ToString()
|
||||
}
|
||||
};
|
||||
|
||||
var destinationFactory = ApplicationDeployerFactory.Create(destinationParameters, loggerFactory);
|
||||
var destinationDeployment = await destinationFactory.DeployAsync();
|
||||
|
||||
return new CorsDeploymentResult(originFactory, originDeployment, secondOriginFactory, secondOriginDeployment, destinationFactory, destinationDeployment);
|
||||
}
|
||||
|
||||
private readonly struct CorsDeploymentResult : IDisposable
|
||||
{
|
||||
public CorsDeploymentResult(
|
||||
ApplicationDeployer originDeployer,
|
||||
DeploymentResult originResult,
|
||||
ApplicationDeployer secondOriginDeployer,
|
||||
DeploymentResult secondOriginResult,
|
||||
ApplicationDeployer destinationDeployer,
|
||||
DeploymentResult destinationResult)
|
||||
{
|
||||
OriginDeployer = originDeployer;
|
||||
OriginResult = originResult;
|
||||
SecondOriginDeployer = secondOriginDeployer;
|
||||
SecondOriginResult = secondOriginResult;
|
||||
DestinationDeployer = destinationDeployer;
|
||||
DestinationResult = destinationResult;
|
||||
}
|
||||
|
||||
public ApplicationDeployer OriginDeployer { get; }
|
||||
|
||||
public DeploymentResult OriginResult { get; }
|
||||
|
||||
public ApplicationDeployer SecondOriginDeployer { get; }
|
||||
|
||||
public DeploymentResult SecondOriginResult { get; }
|
||||
|
||||
public ApplicationDeployer DestinationDeployer { get; }
|
||||
|
||||
public DeploymentResult DestinationResult { get; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
OriginDeployer.Dispose();
|
||||
SecondOriginDeployer.Dispose();
|
||||
DestinationDeployer.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace FunctionalTests
|
||||
{
|
||||
internal static class ProcessManager
|
||||
{
|
||||
private static readonly TimeSpan Timeout = TimeSpan.FromMinutes(3);
|
||||
|
||||
public static Task<ProcessResult> RunProcessAsync(ProcessStartInfo processStartInfo, ILogger logger)
|
||||
{
|
||||
processStartInfo.UseShellExecute = false;
|
||||
processStartInfo.RedirectStandardError = true;
|
||||
processStartInfo.RedirectStandardOutput = true;
|
||||
|
||||
var process = new Process()
|
||||
{
|
||||
StartInfo = processStartInfo,
|
||||
EnableRaisingEvents = true,
|
||||
};
|
||||
|
||||
var output = new StringBuilder();
|
||||
var outputLock = new object();
|
||||
|
||||
process.ErrorDataReceived += Process_ErrorDataReceived;
|
||||
process.OutputDataReceived += Process_OutputDataReceived;
|
||||
|
||||
logger.LogInformation($"Executing command '{process.StartInfo.FileName} {process.StartInfo.Arguments}'");
|
||||
process.Start();
|
||||
process.BeginErrorReadLine();
|
||||
process.BeginOutputReadLine();
|
||||
|
||||
var timeoutTask = Task.Delay(Timeout).ContinueWith((t) =>
|
||||
{
|
||||
// Don't timeout during debug sessions
|
||||
while (Debugger.IsAttached)
|
||||
{
|
||||
Thread.Sleep(TimeSpan.FromSeconds(1));
|
||||
}
|
||||
|
||||
if (process.HasExited)
|
||||
{
|
||||
// This will happen on success, the 'real' task has already completed so this value will
|
||||
// never be visible.
|
||||
return (ProcessResult)default;
|
||||
}
|
||||
|
||||
// This is a timeout.
|
||||
process.Kill();
|
||||
throw new TimeoutException($"command '{process.StartInfo.FileName} {process.StartInfo.Arguments}' timed out after {Timeout}.");
|
||||
});
|
||||
|
||||
var waitTask = Task.Run(() =>
|
||||
{
|
||||
// We need to use two WaitForExit calls to ensure that all of the output/events are processed. Previously
|
||||
// this code used Process.Exited, which could result in us missing some output due to the ordering of
|
||||
// events.
|
||||
//
|
||||
// See the remarks here: https://msdn.microsoft.com/en-us/library/ty0d8k56(v=vs.110).aspx
|
||||
if (!process.WaitForExit(int.MaxValue))
|
||||
{
|
||||
// unreachable - the timeoutTask will kill the process before this happens.
|
||||
throw new TimeoutException();
|
||||
}
|
||||
|
||||
process.WaitForExit();
|
||||
|
||||
string outputString;
|
||||
lock (outputLock)
|
||||
{
|
||||
outputString = output.ToString();
|
||||
}
|
||||
|
||||
return new ProcessResult(processStartInfo, process.ExitCode, outputString);
|
||||
});
|
||||
|
||||
return Task.WhenAny<ProcessResult>(waitTask, timeoutTask).Unwrap();
|
||||
|
||||
void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
logger.LogInformation(e.Data);
|
||||
lock (outputLock)
|
||||
{
|
||||
output.AppendLine(e.Data);
|
||||
}
|
||||
}
|
||||
|
||||
void Process_OutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
logger.LogInformation(e.Data);
|
||||
lock (outputLock)
|
||||
{
|
||||
output.AppendLine(e.Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace FunctionalTests
|
||||
{
|
||||
public readonly struct ProcessResult
|
||||
{
|
||||
public ProcessResult(ProcessStartInfo processStartInfo, int exitCode, string output)
|
||||
{
|
||||
ProcessStartInfo = processStartInfo;
|
||||
ExitCode = exitCode;
|
||||
Output = output;
|
||||
}
|
||||
|
||||
public ProcessStartInfo ProcessStartInfo { get; }
|
||||
public int ExitCode { get; }
|
||||
public string Output { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"jest": "^23.6.0",
|
||||
"merge": "^1.2.1",
|
||||
"puppeteer": "^1.15.0"
|
||||
},
|
||||
"dependencies": {},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,310 +0,0 @@
|
|||
const puppeteer = require('puppeteer');
|
||||
const os = require("os");
|
||||
const hostname = os.hostname();
|
||||
const originPortVar = process.env.ORIGIN_PORT;
|
||||
const destinationPortVar = process.env.DESTINATION_PORT;
|
||||
const secondOriginPortVar = process.env.SECOND_ORIGIN_PORT;
|
||||
|
||||
const corsServerPath = `http://${hostname}:${destinationPortVar}`;
|
||||
|
||||
// e.g., npm test --debug
|
||||
// In debug mode we show the editor, slow down operations, and increase the timeout for each test
|
||||
let debug = process.env.npm_config_debug || false;
|
||||
jest.setTimeout(debug ? 60000 : 30000);
|
||||
|
||||
let browser;
|
||||
let error;
|
||||
|
||||
beforeAll(async () => {
|
||||
const options = debug ?
|
||||
{ headless: false, slowMo: 100 } :
|
||||
{ args: ['--no-sandbox'] };
|
||||
const label = 'Launch puppeteer ';
|
||||
|
||||
console.log('Begin launching puppeteer');
|
||||
console.time(label);
|
||||
|
||||
try {
|
||||
browser = await puppeteer.launch(options);
|
||||
} catch (ex) {
|
||||
error = ex;
|
||||
}
|
||||
console.timeEnd(label);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (browser) {
|
||||
await browser.close();
|
||||
}
|
||||
});
|
||||
|
||||
describe('Browser is initialized', () => {
|
||||
// Workaround for https://github.com/jasmine/jasmine/issues/1533.
|
||||
// Jasmine will not report errors from beforeAll and instead fail all the tests that
|
||||
// expect the browser to be available. This test allows us to ensure the setup was successful
|
||||
// and if unsuccessful report the error
|
||||
test('no errors on launch', () => {
|
||||
expect(error).toBeUndefined();
|
||||
expect(browser).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('CORS allowed origin tests ', () => {
|
||||
const testPagePath = `http://${hostname}:${originPortVar}/`;
|
||||
let page;
|
||||
|
||||
beforeAll(async () => {
|
||||
page = await browser.newPage();
|
||||
await page.goto(testPagePath);
|
||||
});
|
||||
|
||||
test('allows simple GET requests', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-origin`;
|
||||
const options = { method: 'GET', mode: 'cors' };
|
||||
|
||||
const response = await fetch(url, options);
|
||||
return response.status;
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe(200);
|
||||
});
|
||||
|
||||
test('allows simple PUT requests when any method is allowed', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-origin`;
|
||||
const options = { method: 'PUT', mode: 'cors' };
|
||||
|
||||
const response = await fetch(url, options);
|
||||
return response.status;
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe(200);
|
||||
});
|
||||
|
||||
// This one is weird - although the server performs a preflight request and receives a Access-Control-Allow-Methods: PUT,
|
||||
// the browser happily ignores the disallowed POST method.
|
||||
test('allows POST requests when not explicitly allowed', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-header-method`;
|
||||
const options = {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
body: JSON.stringify({ hello: 'world' }),
|
||||
headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' })
|
||||
};
|
||||
|
||||
const response = await fetch(url, options);
|
||||
return response.status;
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe(200);
|
||||
});
|
||||
|
||||
test('allows header to be sent when allowed', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-header-method`;
|
||||
const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }) };
|
||||
|
||||
const response = await fetch(url, options);
|
||||
return response.status;
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe(200);
|
||||
});
|
||||
|
||||
test('does not allow disallowed HTTP Methods', async () => {
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-header-method`;
|
||||
const options = { method: 'DELETE', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }) };
|
||||
|
||||
return await fetch(url, options);
|
||||
}, corsServerPath);
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
test('does not allow disallowed header', async () => {
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-header-method`;
|
||||
const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Not-Test": "value", 'Content-Type': 'application/json' }) };
|
||||
|
||||
return await fetch(url, options);
|
||||
}, corsServerPath);
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
test('does not allow fetch with credentials in non-Preflighted request', async () => {
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-origin`;
|
||||
const options = { method: 'POST', mode: 'cors', credentials: 'include' };
|
||||
|
||||
return await fetch(url, options);
|
||||
}, corsServerPath);
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
test('does not allow fetch with credentials in Preflighted request', async () => {
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-origin`;
|
||||
const options = { method: 'PUT', mode: 'cors', credentials: 'include' };
|
||||
|
||||
return await fetch(url, options);
|
||||
}, corsServerPath);
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
test('allows request with credentials', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-credentials`;
|
||||
const options = { method: 'GET', mode: 'cors', credentials: 'include' };
|
||||
|
||||
const response = await fetch(url, options);
|
||||
return response.status;
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe(200);
|
||||
});
|
||||
|
||||
test('allows Preflighted request with credentials', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-credentials`;
|
||||
const options = {
|
||||
method: 'PUT', mode: 'cors', credentials: 'include', headers: new Headers({
|
||||
'X-Custom-Header': 'X-Custom-Value'
|
||||
})
|
||||
};
|
||||
|
||||
const response = await fetch(url, options);
|
||||
return response.status;
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe(200);
|
||||
});
|
||||
|
||||
test('disallows accessing header when not included in exposed-header', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/exposed-header`;
|
||||
const options = { method: 'GET', mode: 'cors' };
|
||||
|
||||
const response = await fetch(url, options);
|
||||
try {
|
||||
return response.headers.get('x-disallowedheader');
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
test('allows accessing header when included in exposed-header', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/exposed-header`;
|
||||
const options = { method: 'GET', mode: 'cors' };
|
||||
|
||||
const response = await fetch(url, options);
|
||||
try {
|
||||
return response.headers.get('x-allowedheader');
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe("Test-Value");
|
||||
});
|
||||
});
|
||||
|
||||
describe('CORS disallowed origin tests ', () => {
|
||||
const testPagePath = `http://${hostname}:${secondOriginPortVar}/`;
|
||||
let page;
|
||||
|
||||
beforeAll(async () => {
|
||||
page = await browser.newPage();
|
||||
await page.goto(testPagePath);
|
||||
});
|
||||
|
||||
test('allow opaque requests without CORS', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-origin`;
|
||||
const options = { method: 'GET', mode: 'no-cors' };
|
||||
|
||||
// The request will succeed, but we get an opaque filtered response (https://fetch.spec.whatwg.org/#concept-filtered-response).
|
||||
const response = await fetch(url, options);
|
||||
return response.type;
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe("opaque");
|
||||
});
|
||||
|
||||
test('does not allow requests when origin is disallowed', async () => {
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-origin`;
|
||||
const options = { method: 'GET', mode: 'cors' };
|
||||
|
||||
return await fetch(url, options);
|
||||
}, corsServerPath);
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
test('does not allow preflight requests when origin is disallowed', async () => {
|
||||
expect.assertions(1);
|
||||
try {
|
||||
await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-origin`;
|
||||
const options = { method: 'PUT', mode: 'cors' };
|
||||
|
||||
return await fetch(url, options);
|
||||
}, corsServerPath);
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
test('allow requests to any origin endpoint', async () => {
|
||||
const result = await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-all`;
|
||||
const options = { method: 'PUT', mode: 'cors' };
|
||||
|
||||
const response = await fetch(url, options);
|
||||
return response.status;
|
||||
}, corsServerPath);
|
||||
|
||||
expect(result).toBe(200);
|
||||
});
|
||||
|
||||
test('does not allow requests to any origin endpoint with credentials', async () => {
|
||||
expect.assertions(1);
|
||||
|
||||
try {
|
||||
await page.evaluate(async (corsServerPath) => {
|
||||
const url = `${corsServerPath}/allow-all`;
|
||||
const options = { method: 'PUT', mode: 'cors', headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' }), credentials: 'include' };
|
||||
|
||||
const response = await fetch(url, options);
|
||||
return response.status;
|
||||
}, corsServerPath);
|
||||
} catch (e) {
|
||||
expect(e).toBeDefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,47 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SampleDestination
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
using (var host = WebHost.CreateDefaultBuilder(args)
|
||||
.UseUrls("http://+:0")
|
||||
.UseStartup(GetStartupType())
|
||||
.Build())
|
||||
{
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
|
||||
private static Type GetStartupType()
|
||||
{
|
||||
var startup = Environment.GetEnvironmentVariable("CORS_STARTUP");
|
||||
if (startup == null)
|
||||
{
|
||||
return typeof(Startup);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (startup)
|
||||
{
|
||||
case "Startup":
|
||||
return typeof(Startup);
|
||||
case "StartupWithoutEndpointRouting":
|
||||
return typeof(StartupWithoutEndpointRouting);
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Could not resolve the startup type. Unexpected CORS_STARTUP environment variable.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SampleDestination
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
private static readonly string DefaultAllowedOrigin = $"http://{Dns.GetHostName()}:{Environment.GetEnvironmentVariable("ORIGIN_PORT")}";
|
||||
private readonly ILogger<Startup> _logger;
|
||||
|
||||
public Startup(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<Startup>();
|
||||
_logger.LogInformation($"Setting up CORS middleware to allow clients on {DefaultAllowedOrigin}");
|
||||
}
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("AllowOrigin", policy => policy
|
||||
.WithOrigins(DefaultAllowedOrigin)
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader());
|
||||
|
||||
options.AddPolicy("AllowHeaderMethod", policy => policy
|
||||
.WithOrigins(DefaultAllowedOrigin)
|
||||
.WithHeaders("X-Test", "Content-Type")
|
||||
.WithMethods("PUT"));
|
||||
|
||||
options.AddPolicy("AllowCredentials", policy => policy
|
||||
.WithOrigins(DefaultAllowedOrigin)
|
||||
.AllowAnyHeader()
|
||||
.WithMethods("GET", "PUT")
|
||||
.AllowCredentials());
|
||||
|
||||
options.AddPolicy("ExposedHeader", policy => policy
|
||||
.WithOrigins(DefaultAllowedOrigin)
|
||||
.WithExposedHeaders("X-AllowedHeader", "Content-Length"));
|
||||
|
||||
options.AddPolicy("AllowAll", policy => policy
|
||||
.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader());
|
||||
});
|
||||
services.AddRouting();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseRouting();
|
||||
|
||||
app.UseCors();
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.Map("/allow-origin", HandleRequest).RequireCors("AllowOrigin");
|
||||
endpoints.Map("/allow-header-method", HandleRequest).RequireCors("AllowHeaderMethod");
|
||||
endpoints.Map("/allow-credentials", HandleRequest).RequireCors("AllowCredentials");
|
||||
endpoints.Map("/exposed-header", HandleRequest).RequireCors("ExposedHeader");
|
||||
endpoints.Map("/allow-all", HandleRequest).RequireCors("AllowAll");
|
||||
});
|
||||
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
await context.Response.WriteAsync("Hello World!");
|
||||
});
|
||||
}
|
||||
|
||||
private Task HandleRequest(HttpContext context)
|
||||
{
|
||||
var content = Encoding.UTF8.GetBytes("Hello world");
|
||||
|
||||
context.Response.Headers["X-AllowedHeader"] = "Test-Value";
|
||||
context.Response.Headers["X-DisallowedHeader"] = "Test-Value";
|
||||
|
||||
context.Response.ContentType = "text/plain; charset=utf-8";
|
||||
context.Response.ContentLength = content.Length;
|
||||
return context.Response.Body.WriteAsync(content, 0, content.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SampleDestination
|
||||
{
|
||||
public class StartupWithoutEndpointRouting
|
||||
{
|
||||
private static readonly string DefaultAllowedOrigin = $"http://{Dns.GetHostName()}:{Environment.GetEnvironmentVariable("ORIGIN_PORT")}";
|
||||
private readonly ILogger<StartupWithoutEndpointRouting> _logger;
|
||||
|
||||
public StartupWithoutEndpointRouting(ILoggerFactory loggerFactory)
|
||||
{
|
||||
_logger = loggerFactory.CreateLogger<StartupWithoutEndpointRouting>();
|
||||
_logger.LogInformation($"Setting up CORS middleware to allow clients on {DefaultAllowedOrigin}");
|
||||
}
|
||||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddCors();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.Map("/allow-origin", innerBuilder =>
|
||||
{
|
||||
innerBuilder.UseCors(policy => policy
|
||||
.WithOrigins(DefaultAllowedOrigin)
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader());
|
||||
|
||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||
});
|
||||
|
||||
app.Map("/allow-header-method", innerBuilder =>
|
||||
{
|
||||
innerBuilder.UseCors(policy => policy
|
||||
.WithOrigins(DefaultAllowedOrigin)
|
||||
.WithHeaders("X-Test", "Content-Type")
|
||||
.WithMethods("PUT"));
|
||||
|
||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||
});
|
||||
|
||||
app.Map("/allow-credentials", innerBuilder =>
|
||||
{
|
||||
innerBuilder.UseCors(policy => policy
|
||||
.WithOrigins(DefaultAllowedOrigin)
|
||||
.AllowAnyHeader()
|
||||
.WithMethods("GET", "PUT")
|
||||
.AllowCredentials());
|
||||
|
||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||
});
|
||||
|
||||
app.Map("/exposed-header", innerBuilder =>
|
||||
{
|
||||
innerBuilder.UseCors(policy => policy
|
||||
.WithOrigins(DefaultAllowedOrigin)
|
||||
.WithExposedHeaders("X-AllowedHeader", "Content-Length"));
|
||||
|
||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||
});
|
||||
|
||||
app.Map("/allow-all", innerBuilder =>
|
||||
{
|
||||
innerBuilder.UseCors(policy => policy
|
||||
.AllowAnyOrigin()
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader());
|
||||
|
||||
innerBuilder.UseMiddleware<SampleMiddleware>();
|
||||
});
|
||||
|
||||
app.Run(async (context) =>
|
||||
{
|
||||
await context.Response.WriteAsync("Hello World!");
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Cors" />
|
||||
<Reference Include="Microsoft.AspNetCore" />
|
||||
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace SampleDestination
|
||||
{
|
||||
public class SampleMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
|
||||
public SampleMiddleware(RequestDelegate next)
|
||||
{
|
||||
_next = next;
|
||||
}
|
||||
|
||||
public Task Invoke(HttpContext context)
|
||||
{
|
||||
var content = Encoding.UTF8.GetBytes("Hello world");
|
||||
|
||||
context.Response.Headers["X-AllowedHeader"] = "Test-Value";
|
||||
context.Response.Headers["X-DisallowedHeader"] = "Test-Value";
|
||||
|
||||
context.Response.ContentType = "text/plain; charset=utf-8";
|
||||
context.Response.ContentLength = content.Length;
|
||||
return context.Response.Body.WriteAsync(content, 0, content.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace SampleOrigin
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
using (var host = WebHost.CreateDefaultBuilder(args).UseUrls("http://+:0").UseStartup<Startup>().Build())
|
||||
{
|
||||
host.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace SampleOrigin
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseDefaultFiles();
|
||||
app.UseStaticFiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Server.Kestrel" />
|
||||
<Reference Include="Microsoft.AspNetCore" />
|
||||
<Reference Include="Microsoft.Extensions.Logging.Console" />
|
||||
<Reference Include="Microsoft.AspNetCore.StaticFiles" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
<h1>Welcome to the CORS test suite. Please wait...</h1>
|
||||
<a href="test.htm">Click here for the browser test suite.</a>
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<style>
|
||||
.success {
|
||||
background-color: #4CAF50;
|
||||
}
|
||||
</style>
|
||||
<title>CORS Sample</title>
|
||||
</head>
|
||||
<body>
|
||||
<p>CORS Sample</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Scenario</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr id="scenarios"></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
function _fetch(options) {
|
||||
const url = `http://${location.hostname}:9000/${options.testPath}`;
|
||||
options.cors = 'cors';
|
||||
return fetch(url, options);
|
||||
}
|
||||
|
||||
function assertSuccess(options) {
|
||||
return _fetch(options).then(s => true).catch(s => false);
|
||||
}
|
||||
|
||||
function assertFailure(options) {
|
||||
return _fetch(options).then(s => false).catch(s => true);
|
||||
}
|
||||
|
||||
const scenarios = {
|
||||
"Simple GET Request": assertSuccess({
|
||||
testPath: 'allow-origin',
|
||||
method: 'GET'
|
||||
}),
|
||||
|
||||
"Simple PUT Request": assertSuccess({
|
||||
testPath: 'allow-origin',
|
||||
method: 'PUT'
|
||||
}),
|
||||
|
||||
"Disallowed DELETE Method": assertFailure({
|
||||
testPath: 'allow-header-method',
|
||||
method: 'DELETE'
|
||||
}),
|
||||
|
||||
"Allowed Header": assertSuccess({
|
||||
testPath: 'allow-header-method',
|
||||
method: 'PUT',
|
||||
headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' })
|
||||
}),
|
||||
|
||||
// This one is weird - although the server performs a preflight request and receives a Access-Control-Allow-Methods: PUT,
|
||||
// the browser happily ignores the disallowed POST method
|
||||
"Allowed Header Disallowed POST": assertSuccess({
|
||||
testPath: 'allow-header-method',
|
||||
method: 'POST',
|
||||
headers: new Headers({ "X-Test": "value", 'Content-Type': 'application/json' })
|
||||
}),
|
||||
|
||||
"Disallowed Header": assertFailure({
|
||||
testPath: 'allow-header-method',
|
||||
method: 'POST',
|
||||
headers: new Headers({ "Api-Key": "some_key", 'Content-Type': 'application/json' })
|
||||
}),
|
||||
|
||||
"Disallowed Credentials": assertFailure({
|
||||
testPath: 'allow-origin',
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
}),
|
||||
|
||||
"Disallowed Credentials with preflight": assertFailure({
|
||||
testPath: 'allow-origin',
|
||||
method: 'PUT',
|
||||
credentials: 'include'
|
||||
}),
|
||||
|
||||
"Allowed Credentials": assertSuccess({
|
||||
testPath: 'allow-credentials',
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
}),
|
||||
|
||||
"Allowed Credentials with preflight": assertSuccess({
|
||||
testPath: 'allow-credentials',
|
||||
method: 'PUT',
|
||||
credentials: 'include'
|
||||
}),
|
||||
|
||||
"Disallowed exposed header": _fetch({
|
||||
testPath: 'exposed-header',
|
||||
method: 'GET'
|
||||
}).then(response => !response.headers.has("x-disallowedheader")),
|
||||
|
||||
"Allowed exposed header": _fetch({
|
||||
testPath: 'exposed-header',
|
||||
method: 'GET'
|
||||
}).then(response => response.headers.has("x-allowedheader"))
|
||||
};
|
||||
|
||||
const scenariosElement = document.querySelector('#scenarios');
|
||||
Object.keys(scenarios).map(scenario => {
|
||||
const row = document.createElement('tr');
|
||||
row.setAttribute("class", "scenario");
|
||||
scenariosElement.appendChild(row);
|
||||
|
||||
let resultHtml = '<span class="waiting">⌛</span>';
|
||||
const setHtml = () => row.innerHTML = `<td>${scenario}</td><td>${resultHtml}</td>`;
|
||||
|
||||
setHtml();
|
||||
|
||||
return scenarios[scenario].then(result => {
|
||||
resultHtml = result ?
|
||||
'<span class="success">✓</span>' :
|
||||
'<span class="failed">❌<span>';
|
||||
setHtml();
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -243,8 +243,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Crypto
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.DataProtection.Abstractions", "..\DataProtection\Abstractions\src\Microsoft.AspNetCore.DataProtection.Abstractions.csproj", "{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CORS.FunctionalTests", "CORS\test\FunctionalTests\CORS.FunctionalTests.csproj", "{E025D98E-BD85-474A-98A9-E7F44F392F8E}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IISIntegration", "..\Servers\IIS\IISIntegration\src\Microsoft.AspNetCore.Server.IISIntegration.csproj", "{47B6636D-09A3-47AE-9303-9F5D15EEE9D8}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NodeServices", "NodeServices", "{17B409B3-7EC6-49D8-847E-CFAA319E01B5}"
|
||||
|
|
@ -289,10 +287,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Author
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.ConcurrencyLimiter.Microbenchmarks", "ConcurrencyLimiter\perf\Microbenchmarks\Microsoft.AspNetCore.ConcurrencyLimiter.Microbenchmarks.csproj", "{737B26B4-CFC6-4B44-9070-DD36334E85B3}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestDestination", "CORS\test\testassets\TestDestination\TestDestination.csproj", "{DFEB537A-2D35-4C62-8A13-42798DF66A80}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestOrigin", "CORS\test\testassets\TestOrigin\TestOrigin.csproj", "{E0521105-3A7B-480B-B962-0BFC2838D919}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore", "..\DefaultBuilder\src\Microsoft.AspNetCore.csproj", "{46B4FE62-06A1-4D54-B3E8-D8B4B3560075}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IntegrationTesting.IIS", "..\Servers\IIS\IntegrationTesting.IIS\src\Microsoft.AspNetCore.Server.IntegrationTesting.IIS.csproj", "{92E11EBB-759E-4DA8-AB61-A9977D9F97D0}"
|
||||
|
|
@ -1377,18 +1371,6 @@ Global
|
|||
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{47B6636D-09A3-47AE-9303-9F5D15EEE9D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{47B6636D-09A3-47AE-9303-9F5D15EEE9D8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{47B6636D-09A3-47AE-9303-9F5D15EEE9D8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -1581,30 +1563,6 @@ Global
|
|||
{737B26B4-CFC6-4B44-9070-DD36334E85B3}.Release|x64.Build.0 = Release|Any CPU
|
||||
{737B26B4-CFC6-4B44-9070-DD36334E85B3}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{737B26B4-CFC6-4B44-9070-DD36334E85B3}.Release|x86.Build.0 = Release|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Release|x64.Build.0 = Release|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919}.Release|x86.Build.0 = Release|Any CPU
|
||||
{46B4FE62-06A1-4D54-B3E8-D8B4B3560075}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{46B4FE62-06A1-4D54-B3E8-D8B4B3560075}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{46B4FE62-06A1-4D54-B3E8-D8B4B3560075}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
|
|
@ -1746,7 +1704,6 @@ Global
|
|||
{3AD5B221-C718-4F14-883A-4345DC90CF9C} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{227030D6-99AD-4C6A-AE70-1333BCBE8705} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{7343B4E4-C5A2-49E2-B431-4D1E6A26E424} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{E025D98E-BD85-474A-98A9-E7F44F392F8E} = {4967DE1B-FEC2-4C2B-8F7F-6262D67C9434}
|
||||
{47B6636D-09A3-47AE-9303-9F5D15EEE9D8} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{C801B6A3-906F-406F-BA25-EAE0B4BCE5C9} = {17B409B3-7EC6-49D8-847E-CFAA319E01B5}
|
||||
{40951683-DBC4-437A-BBAB-2FA7147E11EA} = {17B409B3-7EC6-49D8-847E-CFAA319E01B5}
|
||||
|
|
@ -1765,8 +1722,6 @@ Global
|
|||
{7E2EA6E2-31FE-418A-9AE4-955A4C708AE7} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{CDDD7C43-5BEB-4E3E-8A59-FCDC83C9FBCF} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{737B26B4-CFC6-4B44-9070-DD36334E85B3} = {8C9AA8A2-9D1F-4450-9F8D-56BAB6F3D343}
|
||||
{DFEB537A-2D35-4C62-8A13-42798DF66A80} = {BD7B3AD8-0BA6-405F-8CF6-24B9464D4B5B}
|
||||
{E0521105-3A7B-480B-B962-0BFC2838D919} = {BD7B3AD8-0BA6-405F-8CF6-24B9464D4B5B}
|
||||
{46B4FE62-06A1-4D54-B3E8-D8B4B3560075} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{92E11EBB-759E-4DA8-AB61-A9977D9F97D0} = {ACA6DDB9-7592-47CE-A740-D15BF307E9E0}
|
||||
{D0CB733B-4CE8-4F6C-BBB9-548EA1A96966} = {D6FA4ABE-E685-4EDD-8B06-D8777E76B472}
|
||||
|
|
|
|||
Loading…
Reference in New Issue