Question
· Oct 16, 2017

Weird No 'Access-Control-Allow-Origin' header issue with Cors

Hi there,

    I'm trying to develop a  program calling Cache REST service twice with Cors. The first is fetching some information of a patient with GET request, the second is using obtained information to call another REST service(implemented in the same class though) with POST to  perform other tasks.

The REST service was implemented as below:

Class WS.Service.REST.AIService Extends %CSP.REST
{

Parameter HandleCorsRequest = 1;

ClassMethod GetPatient(pID As %String) As %Status
{
  #dim tSC As %Status = $$$OK    
  #dim e As %Exception.AbstractException   
  Try {
    #dim patientInstance As HIS.Patient=##class(HIS.Patient).%OpenId(pID)
    set dynamicObject = {}
    set dynamicObject.Id = patientInstance.%Id()

           ....some codes to set the properties....

    set jsonStr = dynamicObject.%ToJSON() 
    w jsonStr                           
  } Catch (e) {        
    Set tSC=e.AsStatus()
  }    
  Quit tSC
}

ClassMethod GetRisk() As %Status
{
  #dim tSC As %Status = $$$OK 
  Do %response.SetHeader("Access-Control-Allow-Origin","*")
  set tSc = ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(%request.Content,"%DynamicObject", .msgInstance)
  #dim patient As WS.Message.Patient = ##class(WS.Message.Patient).%New()

...some codes to set the properties...

  d %response.SetHeader("Access-Control-Allow-Origin","*")
  zw clinicMessage

  quit $$$OK
}

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
<Route Url="/GetRisk" Method="POST" Call="GetRisk" />
<Route Url="/GetPatient/:Id" Method="GET" Call="GetPatient" />
</Routes>
}

Please notice that I've already set Parameter HandleCorsRequest = 1;

also, I override the following two methods in the same service class:

/// This is the CORS request handler. User should override this method in their subclass
/// if they don't want the default behavior
ClassMethod OnHandleCorsRequest(pUrl As %String) As %Status
{

    #dim tSC As %Status = $$$OK
    #dim e As %Exception.AbstractException
    
    #dim %request As %CSP.Request
    #dim %response As %CSP.Response
    
    #dim tOrigin,tHeaders,tMethod As %String
    
    Try {
        
        #; Get the origin
        Set tOrigin=$Get(%request.CgiEnvs("HTTP_ORIGIN"))
            
        #; Allow requested origin
        Do %response.SetHeader("Access-Control-Allow-Origin","*")
       
        #; Set allow credentials to be true
        Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Credentials","true")
        
        #; Allow requested headers
        Set tHeaders=$Get(%request.CgiEnvs("HTTP_ACCESS_CONTROL_REQUEST_HEADERS"))
        Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Headers",tHeaders)
        
        #; Allow requested method
        Set tMethod=$Get(%request.CgiEnvs("HTTP_ACCESS_CONTROL_REQUEST_METHOD"))
        Do ..SetResponseHeaderIfEmpty("Access-Control-Allow-Methods","GET,POST,OPTIONS")
        
    } Catch (e) {
        Set tSC=e.AsStatus()
    }
    Quit tSC
}
ClassMethod OnPreHTTP() As %Boolean [ ServerOnly = 1 ]
{

       d %response.SetHeader("Access-Control-Allow-Credentials","true")
       d %response.SetHeader("Access-Control-Allow-Methods","GET,POST,PUT,OPTIONS")
       d %response.SetHeader("Access-Control-Allow-Origin","*")
       quit 1
}

Then I coded a web page using JQuery to sequencially call the two methods :

The start of the sequence, calling GetPatient first then call GetRisk

var restAddress = "http://192.168.113.132:57772/csp/ai/GetPatient/"
​var riskAddress = "http://192.168.113.132ß:57772/csp/ai/GetRisk/"
function checkPatientRisk(patientID){

var fullUrl = restAddress + patientID

var data = ""

$.ajax

  ({

    type: "GET",

    url: fullUrl,

    dataType: 'json',

    async: true,

    success: function (data){

    displayPatient(data)

    },

    beforeSend: function (xhr) {

    xhr.setRequestHeader ("Authorization", "Basic " + btoa("_system" + ":" + "SYS")); 

}

});

}



function getRisk(patientData){

$.ajax({

        type: "POST",

        url: riskAddress,

        dataType: 'json',

        data: JSON.stringify(patientData),

        success: function(data){

        alert(data);

        },

        beforeSend: function (xhr) {

    xhr.setRequestHeader ("Authorization", "Basic " + btoa("_system" + ":" + "SYS"));

}

    });

}

  

The weird thing with these two calls is that the first GET request is handled while the second call to the POST method failed as belowing:

I wonder why this happens and how may I handle the POST call correctly? Thanks in advance.

Discussion (6)2
Log in or sign up to continue

Here is a possible cause of the 404 error:

An IRIS REST service [or Cache REST service] supports the OPTIONS request (the CORS preflight request – used to determine whether a REST service supports CORS). This request is executed by the CSPSystem user. This user should have READ permission on any databases used by the REST service; if not, the service will respond with an HTTP 404 error.