Monday, December 3, 2012

Allowing cross domain persistence sync to backend database


PersistenceJS comes with client-server example for syncing to backend database. But, when a project complexity reaches a certain level, cross-domain persistence store access might be required. There are many ways to tweak the script for allowing cross-domain access. I was looking for a simple and elegant way to handle this issue, and I found non-other than tweaking the http-header. Tweaking the http-header is a common way to bypass same domain policy.

The purpose of this article is demonstrate the steps to tweak Nodejs web server to support cross domain request so that persistence client hosted on different domain can perform a database sync on the Nodejs web server.

The Server-Side - Setting the http-header
Below is a sample app.js based on todo-app (see my earlier post :). The example below shows the server-side scripting that is required to allow cross-domain access for persistence. The changes are highlighted in YELLOW.

var strVcap = process.env.VCAP_SERVICES || '{"mysql-5.1":[{"name":"mysql-d70a3","label":"mysql-5.1","plan":"free","tags":["mysql","mysql-5.1","relational"],"credentials":{"name":"todoappdb","hostname":"localhost","host":"localhost","port":3306,"user":"root","username":"root","password":"MyNewPass"}}]}';
var jsonVcap = JSON.parse(strVcap);

//persistence declaration
var persistence = require('persistencejs/lib/persistence').persistence;
var persistenceStore = require('persistencejs/lib/persistence.store.mysql');
var persistenceSync = require('persistencejs/lib/persistence.sync.server');

persistenceStore.config(persistence, jsonVcap["mysql-5.1"][0].credentials.host, jsonVcap["mysql-5.1"][0].credentials.port, jsonVcap["mysql-5.1"][0].credentials.name, jsonVcap["mysql-5.1"][0].credentials.username, jsonVcap["mysql-5.1"][0].credentials.password);
persistenceSync.config(persistence);

//init sync
var Todo = persistence.define('todo', {
content: 'TEXT',
done: 'BOOL'
});
Todo.enableSync(); //this create table with sync attribute

//nodejs module declaration
var express = require("express");
var app = express();

//init express
app.use(express.static(__dirname));
app.use(express.bodyParser());
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
var end = res.end;

req.conn = persistenceStore.getSession();
req.conn.schemaSync();
res.end = function() {
req.conn.close();
end.apply(res, arguments);
};
req.conn.transaction(function(tx) {
req.tx = tx;
next();
});
});

app.get('/todoUpdates',  function(req, res) {
console.log(" - get /todoUpdates - " + req.params.uid);
persistenceSync.pushUpdates(req.conn, req.tx, Todo, req.query.since, function(updates) {
res.send(updates);
    });
});

app.post('/todoUpdates',  function(req, res) {
console.log(" - post /todoUpdates - " + req.params.uid);
persistenceSync.receiveUpdates(req.conn, req.tx, Todo, req.body, function(result) {
res.send(result);
});
});

app.get('/markAllDone', function(req, res) {
    Todo.all(req.conn).list(req.tx, function(todo) {
        todo.forEach(function(todo) {
            todo.done = true;
          });
        req.conn.flush(req.tx, function() {
            res.send({status: 'ok'});
                });
      });
});

app.get('/markAllUndone', function(req, res) {
    Todo.all(req.conn).list(req.tx, function(todo) {
        todo.forEach(function(todo) {
            todo.done = false;
          });
        req.conn.flush(req.tx, function() {
            res.send({status: 'ok'});
          });
      });
});

app.listen(process.env.VCAP_APP_PORT || 3303);
console.log('-- Server running at http://127.0.0.1:3303/ --');

The Client-Side - Pointing to the allowed server
Below is a sample persistence client configured to sync to the crossed domain server. The example below shows the client-side script changes required to set to a cross domain server (as highlighted in YELLOW).

Todo.enableSync('http://localhost:3303/todoUpdates');

In Conclusion
By allowing cross domain access to a persistence data store, constraint on web-platform to use only the data store within the same site is eliminated. Thus, all your other web application will be able to use the data store in the web server. This will impact on your web application design (example, single page application or web-portal). On the other hand, there will be needs to properly secure the web server from unwanted attacks.

The example of this tutorial can be downloaded here



1 comment:

Tabat said...

Hi buddies, it is great written piece entirely defined, continue the good work constantly. brand names on sale