PR comments incorporated
This commit is contained in:
parent
7b190ccf0f
commit
fb240d4382
|
|
@ -1,34 +1,35 @@
|
||||||
CORS Sample
|
# CORS Sample
|
||||||
===
|
|
||||||
This sample consists of a request origin (SampleOrigin) and a request destination (SampleDestination).
|
|
||||||
Both have different domain names, to simulate a CORS request.
|
|
||||||
|
|
||||||
Modify Hosts File
|
This sample consists of a request origin (SampleOrigin) and a request destination (SampleDestination). Both have different domain names, to simulate a CORS request.
|
||||||
Windows:
|
|
||||||
|
## Modify Hosts File
|
||||||
|
To run this CORS sample, modify the hosts file to register the hostnames ```destination.example.com``` and ```origin.example.com.```
|
||||||
|
### Windows:
|
||||||
Run a text editor (e.g. Notepad) as an Administrator. Open the hosts file on the path: "C:\Windows\System32\drivers\etc\hosts".
|
Run a text editor (e.g. Notepad) as an Administrator. Open the hosts file on the path: "C:\Windows\System32\drivers\etc\hosts".
|
||||||
|
|
||||||
Linux:
|
### Linux:
|
||||||
On a Terminal window, type "sudo nano /etc/hosts" and enter your admin password when prompted.
|
On a Terminal window, type "sudo nano /etc/hosts" and enter your admin password when prompted.
|
||||||
|
|
||||||
In the hosts file, add the following to the bottom of the file:
|
In the hosts file, add the following to the bottom of the file:
|
||||||
127.0.0.1 destination.example.com
|
``` 127.0.0.1 destination.example.com```
|
||||||
127.0.0.1 origin.example.com
|
``` 127.0.0.1 origin.example.com ```
|
||||||
|
|
||||||
Save the file and close it. Then clear your browser history.
|
Save the file and close it. Then clear your browser history.
|
||||||
|
|
||||||
Run the sample
|
## Run the sample
|
||||||
*In a command prompt window, open the directory where you cloned the repository, and open the SampleDestination directory. Run the command: dotnet run
|
|
||||||
*Repeat the above step in the SampleOrigin directory.
|
|
||||||
*Open a browser window and go to http://origin.example.com:5001
|
|
||||||
*Click the button to see CORS in action.
|
|
||||||
|
|
||||||
The SampleOrigin application will use port 5001, and SampleDestination will use 5000. Please ensure there are no other processes using those ports before running the CORS sample.
|
The SampleOrigin application will use port 5001, and SampleDestination will use 5000. Please ensure there are no other processes using those ports before running the CORS sample.
|
||||||
|
|
||||||
As an example, apart from GET, HEAD and POST requests, PUT requests are allowed in the CORS policy on SampleDestination. Any others, like DELETE, OPTIONS etc. are not allowed and throw an error.
|
* In a command prompt window, open the directory where you cloned the repository, and open the SampleDestination directory. Run the command: dotnet run
|
||||||
Content-Length has been added as an allowed header to the sample. Any other headers are not allowed and throw an error.
|
* Repeat the above step in the SampleOrigin directory.
|
||||||
To edit the policy, please see app.UseCors() method in the Startup.cs file of SampleDestination.
|
* Open a browser window and go to ```http://origin.example.com:5001```
|
||||||
|
* Input a method and header to create a CORS request or use one of the example buttons to see CORS in action.
|
||||||
|
|
||||||
|
As an example, apart from ```GET```, ```HEAD``` and ```POST``` requests, ```PUT``` requests are allowed in the CORS policy on SampleDestination. Any others, like ```DELETE```, ```OPTIONS``` etc. are not allowed and throw an error.
|
||||||
|
```Cache-Control``` has been added as an allowed header to the sample. Any other headers are not allowed and throw an error. You may leave the header name and value blank.
|
||||||
|
|
||||||
|
To edit the policy, please see ```app.UseCors()``` method in the ```Startup.cs``` file of SampleDestination.
|
||||||
|
|
||||||
|
**If using Visual Studio to launch the request origin:**
|
||||||
|
Open Visual Studio and in the ```launchSettings.json``` file for the SampleOrigin project, change the ```launchUrl``` under SampleOrigin to ```http://origin.example.com:5001```.
|
||||||
|
Using the dropdown near the Start button, choose SampleOrigin before pressing Start to ensure that it uses Kestrel and not IIS Express.
|
||||||
|
|
||||||
If using Visual Studio to launch the request origin:
|
|
||||||
Open Visual Studio and in the launchSettings.json file for the SampleOrigin project, change the launchUrl under SampleOrigin to
|
|
||||||
http://origin.example.com:5001. Using the dropdown near the Start button, choose SampleOrigin before pressing Start to ensure that it uses Kestrel
|
|
||||||
and not IIS Express.
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Cors.Infrastructure;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
@ -21,17 +20,18 @@ namespace SampleDestination
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole();
|
||||||
|
|
||||||
app.UseCors(policy => policy
|
app.UseCors(policy => policy
|
||||||
.WithOrigins("http://origin.example.com:5001")
|
.WithOrigins("http://origin.example.com:5001")
|
||||||
.WithMethods("PUT")
|
.WithMethods("PUT")
|
||||||
.WithHeaders("Cache-Control"));
|
.WithHeaders("Cache-Control"));
|
||||||
|
|
||||||
app.Run(async context =>
|
app.Run(async context =>
|
||||||
{
|
{
|
||||||
var responseHeaders = context.Response.Headers;
|
var responseHeaders = context.Response.Headers;
|
||||||
|
context.Response.ContentType = "text/plain";
|
||||||
foreach (var responseHeader in responseHeaders)
|
foreach (var responseHeader in responseHeaders)
|
||||||
{
|
{
|
||||||
await context.Response.WriteAsync("\n"+responseHeader.Key+": "+responseHeader.Value);
|
await context.Response.WriteAsync("\n" + responseHeader.Key + ": " + responseHeader.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.Response.WriteAsync("\nStatus code of your request: " + context.Response.StatusCode.ToString());
|
await context.Response.WriteAsync("\nStatus code of your request: " + context.Response.StatusCode.ToString());
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,4 @@ namespace SampleOrigin
|
||||||
host.Run();
|
host.Run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,19 +18,13 @@ namespace SampleOrigin
|
||||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
|
||||||
{
|
{
|
||||||
loggerFactory.AddConsole();
|
loggerFactory.AddConsole();
|
||||||
app.Run( context =>
|
app.Run(context =>
|
||||||
{
|
{
|
||||||
var fileInfoProvider = env.WebRootFileProvider;
|
var fileInfoProvider = env.WebRootFileProvider;
|
||||||
var fileInfo = fileInfoProvider.GetFileInfo("/Index.html");
|
var fileInfo = fileInfoProvider.GetFileInfo("/Index.html");
|
||||||
context.Response.Headers.Add("Content-Type", "text/html; charset=utf-8");
|
context.Response.ContentType = "text/html";
|
||||||
return context.Response.SendFileAsync(fileInfo);
|
return context.Response.SendFileAsync(fileInfo);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.Run(async context =>
|
|
||||||
{
|
|
||||||
await context.Response.WriteAsync("Status code of your request: " + context.Response.StatusCode.ToString());
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<system.webServer>
|
|
||||||
<handlers>
|
|
||||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
|
||||||
</handlers>
|
|
||||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" forwardWindowsAuthToken="false" stdoutLogEnabled="false" />
|
|
||||||
</system.webServer>
|
|
||||||
</configuration>
|
|
||||||
|
|
@ -41,7 +41,9 @@
|
||||||
var url = 'http://destination.example.com:5000/';
|
var url = 'http://destination.example.com:5000/';
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
request.open(method, url, true);
|
request.open(method, url, true);
|
||||||
request.setRequestHeader(headerName, headerValue);
|
if (headerName && headerValue) {
|
||||||
|
request.setRequestHeader(headerName, headerValue);
|
||||||
|
}
|
||||||
|
|
||||||
if (!request) {
|
if (!request) {
|
||||||
alert('CORS not supported');
|
alert('CORS not supported');
|
||||||
|
|
@ -61,24 +63,11 @@
|
||||||
request.send();
|
request.send();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p>CORS Sample</p>
|
<p>CORS Sample</p>
|
||||||
Method: <input type="text" id="methodName" /><br /><br />
|
Method: <input type="text" id="methodName" /><br /><br />
|
||||||
Header Name: <input type="text" id="headerName" value="Cache-Control" /> Header Value: <input type="text" id="headerValue" value="no-cache" /><br /><br />
|
Header Name: <input type="text" id="headerName" /> Header Value: <input type="text" id="headerValue" /><br /><br />
|
||||||
<script>
|
<script>
|
||||||
document.getElementById('methodName')
|
|
||||||
.addEventListener("keyup", function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
if (event.keyCode == 13) {
|
|
||||||
document.getElementById("headerName").focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
document.getElementById('headerName')
|
|
||||||
.addEventListener("keyup", function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
if (event.keyCode == 13) {
|
|
||||||
document.getElementById("headerValue").focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
document.getElementById('headerValue')
|
document.getElementById('headerValue')
|
||||||
.addEventListener("keyup", function (event) {
|
.addEventListener("keyup", function (event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -91,9 +80,9 @@
|
||||||
<button class="button gray" id="CORS" type="submit" onclick="makeCORSRequest(document.getElementById('methodName').value, document.getElementById('headerName').value, document.getElementById('headerValue').value);">Make a CORS Request</button><br /><br /><br /><br />
|
<button class="button gray" id="CORS" type="submit" onclick="makeCORSRequest(document.getElementById('methodName').value, document.getElementById('headerName').value, document.getElementById('headerValue').value);">Make a CORS Request</button><br /><br /><br /><br />
|
||||||
|
|
||||||
Method DELETE is not allowed:<button class="button red" id="InvalidMethodCORS" type="submit" onclick="makeCORSRequest('DELETE', 'Cache-Control', 'no-cache');">Invalid Method CORS Request</button>
|
Method DELETE is not allowed:<button class="button red" id="InvalidMethodCORS" type="submit" onclick="makeCORSRequest('DELETE', 'Cache-Control', 'no-cache');">Invalid Method CORS Request</button>
|
||||||
Method PUT is allowed:<button class="button green" id="InvalidMethodCORS" type="submit" onclick="makeCORSRequest('PUT', 'Cache-Control', 'no-cache');">Valid Method CORS Request</button><br /><br />
|
Method PUT is allowed:<button class="button green" id="ValidMethodCORS" type="submit" onclick="makeCORSRequest('PUT', 'Cache-Control', 'no-cache');">Valid Method CORS Request</button><br /><br />
|
||||||
|
|
||||||
Header 'Max-Forwards' not supported:<button class="button red" id="InvalidHeaderCORS" type="submit" onclick="makeCORSRequest('PUT', 'Max-Forwards', 'x');">Invalid Header CORS Request</button>
|
Header 'Max-Forwards' not supported:<button class="button red" id="InvalidHeaderCORS" type="submit" onclick="makeCORSRequest('PUT', 'Max-Forwards', '2');">Invalid Header CORS Request</button>
|
||||||
Header 'Cache-Control' is supported:<button class="button green" id="InvalidHeaderCORS" type="submit" onclick="makeCORSRequest('PUT', 'Cache-Control', 'no-cache');">Valid Header CORS Request</button><br /><br />
|
Header 'Cache-Control' is supported:<button class="button green" id="ValidHeaderCORS" type="submit" onclick="makeCORSRequest('PUT', 'Cache-Control', 'no-cache');">Valid Header CORS Request</button><br /><br />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -236,32 +236,32 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
new LogData {
|
new LogData {
|
||||||
origin = "http://example.com",
|
Origin = "http://example.com",
|
||||||
method = "PUT",
|
Method = "PUT",
|
||||||
headers = null,
|
Headers = null,
|
||||||
originLogMessage = "The request has an origin header: 'http://example.com'.",
|
OriginLogMessage = "The request has an origin header: 'http://example.com'.",
|
||||||
policyLogMessage = "Policy execution failed.",
|
PolicyLogMessage = "Policy execution failed.",
|
||||||
failureReason = "Request origin http://example.com does not have permission to access the resource."
|
FailureReason = "Request origin http://example.com does not have permission to access the resource."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
new LogData {
|
new LogData {
|
||||||
origin = "http://allowed.example.com",
|
Origin = "http://allowed.example.com",
|
||||||
method = "DELETE",
|
Method = "DELETE",
|
||||||
headers = null,
|
Headers = null,
|
||||||
originLogMessage = "The request has an origin header: 'http://allowed.example.com'.",
|
OriginLogMessage = "The request has an origin header: 'http://allowed.example.com'.",
|
||||||
policyLogMessage = "Policy execution failed.",
|
PolicyLogMessage = "Policy execution failed.",
|
||||||
failureReason = "Request method DELETE not allowed in CORS policy."
|
FailureReason = "Request method DELETE not allowed in CORS policy."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
new LogData {
|
new LogData {
|
||||||
origin = "http://allowed.example.com",
|
Origin = "http://allowed.example.com",
|
||||||
method = "PUT",
|
Method = "PUT",
|
||||||
headers = new[] { "test" },
|
Headers = new[] { "test" },
|
||||||
originLogMessage = "The request has an origin header: 'http://allowed.example.com'.",
|
OriginLogMessage = "The request has an origin header: 'http://allowed.example.com'.",
|
||||||
policyLogMessage = "Policy execution failed.",
|
PolicyLogMessage = "Policy execution failed.",
|
||||||
failureReason = "Request header 'test' not allowed in CORS policy."
|
FailureReason = "Request header 'test' not allowed in CORS policy."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -276,7 +276,7 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||||
|
|
||||||
var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
|
var corsService = new CorsService(new TestCorsOptions(), loggerFactory);
|
||||||
var requestContext = GetHttpContext(method: "OPTIONS", origin: logData.origin, accessControlRequestMethod: logData.method, accessControlRequestHeaders: logData.headers);
|
var requestContext = GetHttpContext(method: "OPTIONS", origin: logData.Origin, accessControlRequestMethod: logData.Method, accessControlRequestHeaders: logData.Headers);
|
||||||
var policy = new CorsPolicy();
|
var policy = new CorsPolicy();
|
||||||
policy.Origins.Add("http://allowed.example.com");
|
policy.Origins.Add("http://allowed.example.com");
|
||||||
policy.Methods.Add("PUT");
|
policy.Methods.Add("PUT");
|
||||||
|
|
@ -285,9 +285,9 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
var result = corsService.EvaluatePolicy(requestContext, policy);
|
var result = corsService.EvaluatePolicy(requestContext, policy);
|
||||||
|
|
||||||
Assert.Equal("The request is a preflight request.", sink.Writes[0].State.ToString());
|
Assert.Equal("The request is a preflight request.", sink.Writes[0].State.ToString());
|
||||||
Assert.Equal(logData.originLogMessage, sink.Writes[1].State.ToString());
|
Assert.Equal(logData.OriginLogMessage, sink.Writes[1].State.ToString());
|
||||||
Assert.Equal(logData.policyLogMessage, sink.Writes[2].State.ToString());
|
Assert.Equal(logData.PolicyLogMessage, sink.Writes[2].State.ToString());
|
||||||
Assert.Equal(logData.failureReason, sink.Writes[3].State.ToString());
|
Assert.Equal(logData.FailureReason, sink.Writes[3].State.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -1071,14 +1071,14 @@ namespace Microsoft.AspNetCore.Cors.Infrastructure
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct LogData
|
public class LogData
|
||||||
{
|
{
|
||||||
public string origin { get; set; }
|
public string Origin { get; set; }
|
||||||
public string method { get; set; }
|
public string Method { get; set; }
|
||||||
public string[] headers { get; set; }
|
public string[] Headers { get; set; }
|
||||||
public string originLogMessage { get; set; }
|
public string OriginLogMessage { get; set; }
|
||||||
public string policyLogMessage { get; set; }
|
public string PolicyLogMessage { get; set; }
|
||||||
public string failureReason { get; set; }
|
public string FailureReason { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue