Reputation: 23
I am running a small web app using AngularJS, running on an IIS8.5 server, and using DreamFactory for the API. I am running into an issue with CORS when trying to make $http requests in a service.
The errors keep suggesting that the Access-Control-Allow-Headers values are empty in the web.config file; however, that is not the case.
I receive this error when trying to send an API request: "Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response." I also get the X-DreamFactory-API-Key listed in the error when that is uncommented in the header request.
My $http call looks like this:
$http({ method: 'POST', headers: { 'X-DreamFactory-API-Key':'apiKey' },...
My web.config file has:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type, Accept, Origin, X-Requested-With, X-DreamFactory-API-Key" />
<add name="Access-Control-Allow-Methods" value="GET,POST,PUT,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Credentials" value="true" />
</customHeaders>
</httpProtocol>
This is the configuration at the root level, which has been pushed down to the site level.
I have also setup CORS in the Dreamfactory admin console.
Does anyone have ANY clue as to what is happening and how to fix this? Thanks.
Upvotes: 1
Views: 1515
Reputation: 3418
As you've realized, pre-flight CORS in ASP.NET doesn't work too well. I haven't used DreamFactory and I'm on IIS 7.5, however, the same most likely apply.
I solved this using a custom HttpModule.
public class CorsModule : IHttpModule
{
public void Dispose() {
// There's nothing to dispose here, but the dispose implementation is required.
}
public void Init(HttpApplication context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
// Without this .NET sends a weird status code, can't remember what exactly.
context.PreSendRequestHeaders += delegate
{
if (context.Request.HttpMethod == "OPTIONS")
{
var response = context.Response;
response.StatusCode = (int)HttpStatusCode.OK;
}
};
// Bind to the Application_BeginRequest event. This is the important part right here.
context.BeginRequest += this.Application_BeginRequest;
}
private void Application_BeginRequest(Object source, EventArgs e)
{
// Personally I only needed to send those headers in the OPTIONS method.
// You might need to change this for your needs.
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Authorization, Origin, Content-Type, Accept, X-Requested-With, SOAPAction");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
The only thing that I needed in my web.config is the Access-Control-Allow-Origin
, Access-Control-Allow-Credentials
and a reference to my HttpModule:
<modules>
<add name="CorsModule" type="MyNamespace.CorsModule, MyAssembly" />
</modules>
Upvotes: 1