Sunday, February 2, 2014

CORS - Cross Origin Resource Sharing using CouchDB

Recently I tried to build a simple application which creates simple math questions, and records the time taken by the student to finish one page of questions. The short story is that I finally succeeded in implementing the question generation by using Javascript without any server side programming. But what about recording the time taken? We need some database in some server for that.
I want to use a database, but I don't want to  code server-side. So I guess CouchDB is a good choice, given that it supports REST-based API and all. It turned out that calling HTTP REST service from  the browser is much more complicated than calling the same service from the server.
To make a long story short, here is what I found :
  1. Javascript running in a page in a web browser are not allowed to call urls outside the domain of the page. 
  2. Except, when the server serving the URL specifically allowed this by giving Cross Origin Resource Sharing header.
  3. Credentials passing is doubly difficult, because there is a separate Allow Credentials header required, and the involvement of preflight requests, which is a http request with OPTIONS method that were issued before the actual request. The facts are :
    1. Credentials will not be passed when the browser is doing a preflight request
    2. Simple requests, with custom Authentication header (containing the said credentials), will be performed using preflight request first because the existence of such header
    3. Some CouchDB servers will reject the OPTIONS header when were requested in some URL, with not authorized HTTP status.
    4. Debugging CORS in Firebug/Firefox is a nightmare. Use Chrome for better sanity.
  4. Cloudant CouchDB server will not give CORS header for _uuid URL.  This might be true for other servers. CORS configuration must be done using curl (see this gist)
  5. Couchappy CouchDB server keeps requesting authentication even for OPTIONS request. Couchappy have CORS section in the configuration.
  6. My Iriscouch CouchDB server have intermittent availability problems. Unreliable for development use. Something wrong might happened during my registration/service provisioning. Iriscouch keeps showing no CORS header even after I enabled it in the Futon configuration.
My first success is obtained by :
  1. Using cloudant server, configure CORS using curl with allow_credentials false and allow-origin *.
    curl -k -i -u username  -X PUT https://username.cloudant.com/_api/v2/user/config/cors -H "Content-Type: application/json" -d '{"enable_cors":true,"allow_credentials":false,"allow_methods":["GET","PUT","POST","DELETE","OPTIONS"],"origins":{"*":{}}}'
  2. Configure the database using Cloudant's Dashboard UI so Everyone has write and read access
  3. Call the CouchDB API using jquery :
        docdata = '{"level" : "' + currentExercise.level + '", "sheet" : ' + currentExercise.sheet
        + ', "msecs" : '+s.diff + ', "acc" : ' + s.score + ', "d" : "'+datetime +'"}';
        $.ajax({
            url: baseUrl + "/sheet_submission",
            data: docdata,
            type: 'POST',
            dataType: 'json',
            contentType: 'application/json',            error: function() {
                alert('document save failed :' + docdata);
            },
            success: function (d1,st1,jq1) {
                alert('doc save ok : ' + docdata);
                recordCallback();
            }
        });          

3 comments:

Recycling Guy said...

I've been on the same journey you describe regarding ramping up my CORS knowledge. The couchDB documentation and examples all use cURL for demonstration, and I think having javascript examples would be helpful.. I'm at a point where my app works in Chrome, but not in FF. The preflight OPTIONS request is getting 401ed; cause is no 'Access-Control-Allow-Origin' header on the response... where as the exact same request in Chrome does get the 'Access-Control-Allow-Origin' from couchDB... yet to track down the cause... please let me know if you have any ideas.

Michele Ferrari said...

Hi guys, I am on the same boat. Have you tried to use $.couch.login and then write with $.couch.db(name).saveDoc(...)?

Nitesh Kumar said...

I really appreciate information shared above. It’s of great help. If someone want to learn Online (Virtual) instructor lead live training in Couch DB, kindly contact us http://www.maxmunus.com/contact
MaxMunus Offer World Class Virtual Instructor led training on Couch DB. We have industry expert trainer. We provide Training Material and Software Support. MaxMunus has successfully conducted 100000+ trainings in India, USA, UK, Australlia, Switzerland, Qatar, Saudi Arabia, Bangladesh, Bahrain and UAE etc.
For Demo Contact us.
Nitesh Kumar
MaxMunus
E-mail: nitesh@maxmunus.com
Skype id: nitesh_maxmunus
Ph:(+91) 8553912023
http://www.maxmunus.com/