Sunday, April 1, 2012

Setting and retrieving LockerProject data in a local install


I've been trying to play with LockerProject from Singly, and I'd like to use data other than the built-in types of contacts, links, photos, and places.  (You can see one project that motivates me at familyhistories.info.)  There are ways to build new connectors and collections that support rich functionality like syncing, but there is also a simple Push API that allows for arbitrary data, so I've started by playing with that.  Following are some changes I had to make to get things working.

We can send and retrieve arbitrary data via curl, and those examples work great.

Set:
curl -H "Content-Type: application/json" \  
--data-binary '{"data":[{"id":42,"question":"my test"}]}' \  
http://localhost:8042/push/foo 
 
ok

Get:
curl http://localhost:8042/push/foo/42
 
{"_id":"4f2752c03f670f3343f7fed0","id":42,"question":"my test"}

Unfortunately, things don't work as smoothly when trying to do it in an app.  Let's start with retrieval.  First of all, we need get data from the local locker instead of the one at singly.com.  The best approach I can think is to tweak the APIClient so that we can specify which host, so instead of "new APIClient()" we can do the following:
new APIClient({baseUrl:'http://localhost:8042'})
Great.

Except now my browser won't retrieve the value via AJAX; Chrome is the most helpful, and it tells me:
Origin null is not allowed by Access-Control-Allow-Origin.
The only way I can figure to get past this is to modify LockerProject.  So I've added the following to the Ops/webservice.js file as the first line in the first function argument to express.createServer:

// "*" works for all domains; null and "X-Requested-With" work for file:// URLs in Firefox but not Chrome
res.header("Access-Control-Allow-Origin", "*");
Cool.  Now I can retrieve values that I've inserted.  This might not be a great solution, and I haven't thought through the security complications so that I can submit it to LockerProject, but I'm just going to live with it on my machine.

Unfortunately, this is where we're stuck.  It's easy enough to add a post to insert data, but there is a problem within the parsing of JSON in the locker server: it takes any values as strings, so even though we send an update/insert like the data above with a numeric ID of 42, it ends up inserting some data with a string ID of "42"... and we can't retrieve that value with the typical GET request (above)... in fact, I cannot find any way to retrieve that data through the API.  You can see it as it gets processed in the web server and you can see it inside your mongo DB.  Most unfortunate.

In summary, to get arbitrary data from your local locker in a browser app:
  • patch the locker server (see Access-Control-Allow-Origin above)
  • use the client customizations (demonstrated here in the singly-api-local.js and the test-new-datatype.html files)
To set arbitrary data in your local locker in a browser app... you're out of luck due to the string problem.

Maybe there's a better way...?


No comments: