Settting Access-Control-Allow-Origin

Hi,

My testing to your backend is done using a HTML 5 test harness making a REST call to a NodeJS script. I’m having issue with getting a 0 return status, which typically indicates cross site issues. If you can set the value of “Access-Control-Allow-Origin” at your end, this should allow it to work. Not sure if I also need “Access-Control-Max-Age” and several other too.

Is this something I can control, or you can enable?

Thanks
Paul

Hi, Paul,

You can set any header you need in your script yourself: http://expressjs.com/4x/api.html#res.set

But aren’t these headers only applicable on an “OPTIONS” method request, not POST or GET etc? I wouldn’t be able to get access to the OPTIONS request, that would be intercepted by your web server right?

By the way, I’m using a script that I’m posting to. The code starts with:

exports.run = function(request, response)
{

}

Paul,

It would be helpful if you could show what requests go out, to what URL, what headers are sent and what you get back.

Any CORS request starts with a pre-flight request which is OPTIONS. That request is sort of a handshake between the client and the server. All of the CORS headers are established there.

We would need to see more details to be able to help you.

Regards,
Mark

Seems I now understand what’s the problem.
We’ll consider adding OPTIONS request possibility.

Hi Mark,

I have a nodeJS web server that I built to test while I wasn’t connected to backendless. It simulates all the scripts and db that I need, and it also handles the OPTIONS request prior to POST. I can’t get the outgoing info, the language I use (Monkey-X) doesn’t allow me to see that. But I have included the input to my NodeJS web server.

This is the OPTIONS pre-request. Below is the actual request with the additional headers I set in my webserver. Note: this is debugging from WebStorm.

req = IncomingMessage
 client = Socket
 complete = false
 connection = Socket
 domain = null
 headers = Object
  accept = "*/*"
  accept-encoding = "gzip, deflate, sdch"
  accept-language = "en-US,en;q=0.8"
  access-control-request-headers = "application-id, application-type, content-type, secret-key, user-token"
  access-control-request-method = "POST"
  connection = "keep-alive"
  host = "127.0.0.1:1337"
  origin = "http://localhost:60222"
  referer = "http://localhost:60222/MonkeyGame.html"
  user-agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36"
  __proto__ = Object
 httpVersion = "1.1"
 httpVersionMajor = 1
 httpVersionMinor = 1
 method = "OPTIONS"
 rawHeaders = Array[20]
 rawTrailers = Array[0]
 readable = true
 socket = Socket
 statusCode = null
 statusMessage = null
 trailers = Object
 upgrade = false
 url = "/xxx/v1/files/web/scripts/sitg/getmembermain.js"
 _consuming = false
 _dumped = false
 _events = Object
 _maxListeners = undefined
 _pendingIndex = 0
 _pendings = Array[0]
 _readableState = ReadableState
 __proto__ = IncomingMessage
res = ServerResponse
req.headers = Object
req.headers.origin = "http://localhost:60222"
this = Server

POST request data.

req = IncomingMessage
 client = Socket
 complete = false
 connection = Socket
 domain = null
 headers = Object
  accept = "*/*"
  accept-encoding = "gzip, deflate"
  accept-language = "en-US,en;q=0.8"
  application-id = "xxx"
  application-type = "REST"
  connection = "keep-alive"
  content-length = "15"
  content-type = "application/json, application/json"
  host = "127.0.0.1:1337"
  origin = "http://localhost:60222"
  referer = "http://localhost:60222/MonkeyGame.html"
  secret-key = "xxx"
  user-agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.99 Safari/537.36"
  user-token = "XXXX"
  __proto__ = Object
 httpVersion = "1.1"
 httpVersionMajor = 1
 httpVersionMinor = 1
 method = "POST"
 rawHeaders = Array[28]
 rawTrailers = Array[0]
 readable = true
 socket = Socket
 statusCode = null
 statusMessage = null
 trailers = Object
 upgrade = false
 url = "/xxx/v1/files/web/scripts/sitg/getmembermain.js"
 _consuming = false
 _dumped = false
 _events = Object
 _maxListeners = undefined
 _pendingIndex = 0
 _pendings = Array[0]
 _readableState = ReadableState
 __proto__ = IncomingMessage
res = ServerResponse
req.headers = Object
req.headers.origin = "http://localhost:60222"
this = Server

Do you have the responses for both of these requests? (with headers and bodies)

These are in the debugger just before sending back. I can’t get the response in the app itself.

OPTIONS response

req = IncomingMessage
res = ServerResponse
 chunkedEncoding = true
 connection = null
 domain = null
 finished = true
 output = Array[0]
 outputCallbacks = Array[0]
 outputEncodings = Array[0]
 sendDate = true
 shouldKeepAlive = true
 socket = null
 statusCode = 200
 statusMessage = "OK"
 useChunkedEncodingByDefault = true
 writable = true
 _events = Object
 _hangupClose = false
 _hasBody = true
 _header = "HTTP/1.1 200 OK\r\nAccess-Control-Allow-Origin: http://localhost:60367\r\nAccess-Control-Allow-Methods: POST\r\nAccess-Control-Allow-Headers: application-id, application-type, content-type, secret-key, user-token\r\nAccess-Control-Max-Age: 31536000\r\nDate: Sun, 27 Sep 2015 21:55:36 GMT\r\nConnection: keep-alive\r\nTransfer-Encoding: chunked\r\n\r\n"
 _headerNames = Object
 _headerSent = true
 _headers = Object
  access-control-allow-headers = "application-id, application-type, content-type, secret-key, user-token"
  access-control-allow-methods = "POST"
  access-control-allow-origin = "http://localhost:60367"
  access-control-max-age = 31536000
  __proto__ = Object
 _last = false
 _maxListeners = undefined
 _removedHeader = Object
 _trailer = ""
 __proto__ = ServerResponse
req.headers = Object
req.headers.origin = "http://localhost:60367"
this = Server

POST response

latestMemberDist = MemberDist
memberMain = MemberMain
previousMemberDist = undefined
response = Object
 res = ServerResponse
  chunkedEncoding = false
  connection = Socket
  domain = null
  finished = false
  output = Array[0]
  outputCallbacks = Array[0]
  outputEncodings = Array[0]
  sendDate = true
  shouldKeepAlive = true
  socket = Socket
  useChunkedEncodingByDefault = true
  writable = true
  _events = Object
  _hangupClose = false
  _hasBody = true
  _header = null
  _headerNames = Object
  _headerSent = false
  _headers = Object
  _last = false
  _maxListeners = undefined
  _removedHeader = Object
  _trailer = ""
  __proto__ = ServerResponse
 status = 200
 __proto__ = Object
str = "{"___class":"MemberMain","objectId":"5","created":null,"updated":1443079792943,"joinDate":null,"userId":"55","memberDistId":""}"
this = global

You previously wrote you’re getting “0 return status”. In the messages you posted I see the return status is 200, which is what’s expected. I do not see anything wrong with the messages, but the data is still not formatted quite right.

Hi Mark,

This is the response from my personal NodeJS web server, not backendless. I cannot get this level of data from backendless, as my programming language doesn’t offer it to me. All I can see is status code of 0, and response message of blank.

Try putting a debug proxy server between your machine and Backendless to capture the network traffic. There are several available, for example Charles Proxy. Without that data, there is very little we can do to help.

Does your webserver (that handles script JS files), handle OPTIONS request? What does it do with the Origin headers?

We definitely handle it on the API side. I need to check if it is processed on the hosted scripts (node.js) side as well. I will let you know.

Hi, Paul,
Did you try doing OPTIONS request to the script manually? I just checked it, and you should be getting the following headers in response:

    Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, PATCH Access-Control-Allow-Headers: origin, application-id, application-type, content-type, secret-key, request, user-token, unique-method-name Access-Control-Max-Age: 1728000

My webserver (apache) log shows that it is doing an OPTIONS request for *, and it gets back 200 with no message. However, my code receives 0 status code. I’ll have to do some more digging.

The OPTIONS request is not supposed to return any body (this is what I believe you call “message”). It only returns the mentioned headers and 200 response code.

As Mark mentioned above, Charles Proxy could help you debug the requests and responses.

I will take a look at the proxy. It’s strange that everything works perfectly with my simple nodeJS web server. I’m executing the same JS scripts as I have deployed to your server. Either, something is different in the way the OPTIONS is being treated. Or, there’s an error in my script that is not apparently when I run it locally (probably because I’m simulating the Data Store). I did notice when I tried to call OPTIONS directly with a test harness app (PAW), I got a 400 error. This could indicate a bug in script when running in your service. I’ll keep digging.

Thanks for your help and advice