Cross Domain Ajax Requests

I'm rather late to the party with this one, but I had always understood it to be the case that it was not possible to make cross domain ajax requests. That means that if I have JavaScript running on www.domaina.com it can't make a request to www.domainb.com. This was what JSONP was invented for and it worked fine, at least for GET requests.

But I'm in the process of writing an application which Mark and I are going to use in our IBM Connect session in January and I thought I'd investigate what the current options were. I'm very glad I did as there is now an officially supported option to allow cross domain ajax requests.

What we need to do is make a couple of configuration changes to the Domino server, and then also make sure that our ajax request is crafted very carefully indeed.

So first, the Domino server. I'm going to assume you're running with Internet Sites enabled, so you open your internet site document and add a new Rule document from it.

In this example, I have set the rule to only apply to a single XPage in my application called api.xsp. You can obviously build your own rule here. The expires header I just left with the defaults and then the important bit is the custom headers. We add two here:

First is "Access-Control-Allow-Origin" which I have set to "*" but you can configure to only allow specific domains to make a remote ajax request from.

Second may or may not be needed depending on your situation. I am wanting to post JSON data to the XPage which I will then read and do something with. I found that if I didn't add this second setting of "Access-Control-Allow-Headers" with a value of "Origin, X-Requested-With, Content-Type, Accept" that the server would throw an error of "Cannot use bufferedreader while servletinputstream is in use" when I tried to read the posted data.

The usual caveats apply about the configuration of this, run it past the significant admin in your life to make sure that no security vulnerabilities are being opened up. In my case I am creating a demo so am not too worried.

On the client side, your ajax request has to be very carefully crafted. I am using jQuery to do the POST for me in this format:

$.ajax({
type: "POST",
url: "http://www.domainb.com/ibmconnect/approvals.nsf/api.xsp/" + id,
data: JSON.stringify({"status":newstatus}), 
cache: false, 
complete: getMyRequests,
headers: { "Content-Type": "application/json"},
dataType: "json",
error: function(request, error) {
console.log(arguments);
}
});

The key things to note are that the data property is wrapped with JSON.stringify and that the headers property has been completed.

Be aware that not all browsers support this. This article covers in detail the issues which you may face with IE8 and 9 (basically you'll have to hand craft you're own ajax requests rather than relying on a library).

The other thing which I discovered is that the REST services in the Extension Library do not honour the Web Site Rules, so they will not add the required headers. So if you want to do this you will have to hand craft your own REST service in Java. To be honest, having played with the Extension Library REST Services, they don't do what I need anyway so it's not a great hardship, but as ever YMMV.