2

i'm trying to send a POST request to a REST web service from a different domain in FireFox. i'm using the JavaScript "fetch" function for this. i'm hosting the REST web service in IIS. it works fine before i add a "Content-Type" header in JavaScript.

CORS errors in the FireFox console

note that if i enable XHR in the console, then i can see that using fetch with the "Content-Type" results in an OPTIONS request. but, not using the "Content-Type" results in a POST request. so fetch is triggering a preflight request as the documentation says. these are the errors:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://example.com/Service.svc/Request. (Reason: CORS preflight response did not succeed).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://example.com/Service.svc/Request. (Reason: CORS request did not succeed).
TypeError: NetworkError when attempting to fetch resource.

JavaScript with CORS error

var body = '{ID:2, Name:"test reqx"}';
var url = "http://example.com/Service.svc/Request";
var init = {credentials:"include", method:"POST", headers:{"Content-Type":"application/json","Accept":"application/json"}, body:body};
fetch(url,init)
    .then(response => response.text())
    .then(data => console.log(data));

JavaScript without CORS error, but also no Content-Type

var body = '{ID:2, Name:"test reqx"}';
var url = "http://example.com/Service.svc/Request";
var init = {credentials:"include", method:"POST", headers:{"Accept":"application/json"}, body:body};
fetch(url,init)
    .then(response => response.text())
    .then(data => console.log(data));

i'm using 'credentials:"include"' because the REST web service is configured with Basic Authentication.

REST web service web.config (note the different domain)

i've added some CORS configurations, to make other requests work cross domain in FireFox. but, i can't find the right configuration to allow Content-Type:

<configuration>
    ...
    <system.webServer>
      <httpProtocol>
        <customHeaders>
          <add name="Access-Control-Allow-Origin" value="http://example.net" />
          <add name="Access-Control-Allow-Methods" value="OPTIONS,POST"/>
          <add name="Access-Control-Allow-Credentials" value="true" />
          <add name="Access-Control-Allow-Headers" value="Content-Type"/>
        </customHeaders>
      </httpProtocol>
      ...
    </system.webServer>
    ...
</configuration>

the REST web service does not work without the "Content-Type" header "application/json". how can i resolve these errors?

Side note

using HTTP instead of HTTPS, makes the examples easier (because no certificates needed), but it also sends the credentials for Basic Authentication in plain text

symbiont
  • 1,428
  • 3
  • 21
  • 27
  • check this if it helps. https://stackoverflow.com/questions/43759938/making-fetch-api-work-with-cors-after-options-response – Nishant Jun 19 '20 at 12:11
  • try adding a CORS plugin to chrome and check if it returns a response then you might need to do some header value changes, else code changes – Nishant Jun 19 '20 at 12:12
  • @Nishant which plugin? if what returns response? the web service responds when not using the Content-Type header – symbiont Jun 19 '20 at 12:58
  • try this chrome extension, and check if you get the response with content-type. https://chrome.google.com/webstore/detail/allow-cors-access-control/lhobafahddgcelffkeicbaginigeejlf?hl=en#:~:text=Allow%20CORS%3A%20Access%2DControl%2DAllow%2DOrigin%20lets%20you,default%20(in%20JavaScript%20APIs). – Nishant Jun 19 '20 at 13:01
  • 1
    @Nishant that isn't helpful to users of the OPs application. – Daniel A. White Jun 19 '20 at 13:11
  • 1
    @symbiont i see you using wcf - have you configured it to respond to the OPTIONS request? the custom headers stuff is insufficient if that returns an error response code. – Daniel A. White Jun 19 '20 at 13:12
  • @DanielA.White yeah. it's a wcf service. i haven't changed anything except the customHeaders. the OPTIONS request is getting a 401 Unauthorized response. where would i configure the OPTIONS response? – symbiont Jun 19 '20 at 13:24
  • 1
    @symbiont https://stackoverflow.com/questions/14047754/how-to-add-cross-domain-support-to-wcf-service – Daniel A. White Jun 19 '20 at 13:26
  • @DanielA.White thanks for the suggestion. i will have to try that out – symbiont Jun 19 '20 at 15:49
  • Have you fixed it by setting response for OPTIONS? – Jokies Ding Jun 22 '20 at 08:13
  • @JokiesDing will hopefully get the chance to try it today. i will update this question when i know – symbiont Jun 22 '20 at 11:11
  • @DanielA.White thanks! that led to the solution – symbiont Jun 25 '20 at 19:44
  • @JokiesDing yes it's fixed now. i put the details in an answer – symbiont Jun 25 '20 at 19:45

1 Answers1

1

the selected answer, in the question referred to by Daniel A. White, was the solution although slightly modified. How to add cross domain support to WCF service.

Side note

i noticed different responses to the OPTIONS call when it's not yet fixed:

  • 405 Method Not Allowed: with Anonymous Authentication in IIS
  • 401 Unauthorized: with Basic Authentication in IIS but the CORS errors are the same in both cases as Daniel pointed out

this is how i modified the WCF REST Web Service and got rid of the CORS errors:

Global.asax.cs

i also added the Global.asax.cs file to the web service. but i did not add any "Access-Control-Allow-Headers" in there, as it seems to overrule the web.config. so decided to shave it down to the bare minimum:

    protected void Application_BeginRequest(object sender, EventArgs e)
    {
        // prevent 401 unauthorized response to CORS preflight check
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        {
            HttpContext.Current.Response.End();
        }
    }

Web.config

i shaved this down to the bare minimum as well (make sure you have runAllManagedModulesForAllRequests="true")

<configuration>
  ...
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    ...
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="http://example.net" />
        <add name="Access-Control-Allow-Credentials" value="true" />
        <add name="Access-Control-Allow-Headers" value="Content-Type"/>
      </customHeaders>
    </httpProtocol>
    ...
  </system.webServer>
  ...
</configuration>
symbiont
  • 1,428
  • 3
  • 21
  • 27