Awesome
This package is forked from crazytoad/meteor-collectionapi
Table of Contents
Collection API
Easily perform CRUD operations on Meteor Collections over HTTP/HTTPS from outside of the Meteor client or server environment.
Current version: 0.3.0 (Requires Meteor v1.3.1+)
Warning: versions 0.1.18+ are not compatible with versions less than 0.1.18 if you use before functions! Because we change the before functions call parameters.
Installation
Just run this in your app:
$ meteor add xcv58:collection-api
It's that easy! Be sure to check out other cool packages over at Atmosphere.
Windows support
Please use meteor add xcv58:collection-api@=0.2.6
to install 0.2.6
if you got No compatible binary build found for this package
error.
Quick Setup
Players = new Meteor.Collection("players");
if (Meteor.isServer) {
Meteor.startup(function () {
// All values listed below are default
collectionApi = new CollectionAPI({
authToken: undefined, // Require this string to be passed in on each request
apiPath: 'collectionapi', // API path prefix
standAlone: false, // Run as a stand-alone HTTP(S) server
allowCORS: false, // Allow CORS (Cross-Origin Resource Sharing)
sslEnabled: false, // Disable/Enable SSL (stand-alone only)
listenPort: 3005, // Port to listen to (stand-alone only)
listenHost: undefined, // Host to bind to (stand-alone only)
privateKeyFile: 'privatekey.pem', // SSL private key file (only used if SSL is enabled)
certificateFile: 'certificate.pem', // SSL certificate key file (only used if SSL is enabled)
timeOut: 120000
});
// Add the collection Players to the API "/players" path
collectionApi.addCollection(Players, 'players', {
// All values listed below are default
authToken: undefined, // Require this string to be passed in on each request.
authenticate: undefined, // function(token, method, requestMetadata) {return true/false}; More details can found in [Authenticate Function](#Authenticate-Function).
methods: ['POST','GET','PUT','DELETE'], // Allow creating, reading, updating, and deleting
before: { // This methods, if defined, will be called before the POST/GET/PUT/DELETE actions are performed on the collection.
// If the function returns false the action will be canceled, if you return true the action will take place.
POST: undefined, // function(obj, requestMetadata, returnObject) {return true/false;},
GET: undefined, // function(objs, requestMetadata, returnObject) {return true/false;},
PUT: undefined, // function(obj, newValues, requestMetadata, returnObject) {return true/false;},
DELETE: undefined // function(obj, requestMetadata, returnObject) {return true/false;}
},
after: { // This methods, if defined, will be called after the POST/GET/PUT/DELETE actions are performed on the collection.
// Generally, you don't need this, unless you have global variable to reflect data inside collection.
// The function doesn't need return value.
POST: undefined, // function() {console.log("After POST");},
GET: undefined, // function() {console.log("After GET");},
PUT: undefined, // function() {console.log("After PUT");},
DELETE: undefined // function() {console.log("After DELETE");},
}
});
// Starts the API server
collectionApi.start();
});
}
Newer configurations of Meteor may require import { CollectionAPI } from 'meteor/xcv58:collection-api';
.
Note that requestMetadata is a JSONObject that contains
collectionPath
, collectionId
, fields
, and query
from request.
Some values may be undefined
if request doesn't have such parts.
curl http://localhost:3000/collectionapi/players/id/field/subfield?query1=1&query2=2 -d '{"a" : 1}'
requestMetadata = {
collectionPath: 'players',
collectionId: 'id',
fields: [ 'field', 'subfield' ],
query: {
query1: '1',
query2: '2'
}
}
Using the API
If you specify an authToken
it must be passed in either the X-Auth-Token
request header or as an auth-token
param in the query string.
API Usage Example
If you already did Quick Setup part, please ignore the setup code snippet below:
Players = new Meteor.Collection("players");
if (Meteor.isServer) {
Meteor.startup(function () {
collectionApi = new CollectionAPI({ authToken: '97f0ad9e24ca5e0408a269748d7fe0a0' });
collectionApi.addCollection(Players, 'players');
collectionApi.start();
});
}
Get all of the player records:
$ curl -H "X-Auth-Token: 97f0ad9e24ca5e0408a269748d7fe0a0" http://localhost:3000/collectionapi/players
Get an individual record:
$ curl -H "X-Auth-Token: 97f0ad9e24ca5e0408a269748d7fe0a0" http://localhost:3000/collectionapi/players/c4acddd1-a504-4212-9534-adca17af4885
Create a record:
$ curl -H "X-Auth-Token: 97f0ad9e24ca5e0408a269748d7fe0a0" -d "{\"name\": \"John Smith\"}" http://localhost:3000/collectionapi/players
Update a record:
$ curl -H "X-Auth-Token: 97f0ad9e24ca5e0408a269748d7fe0a0" -X PUT -d "{\"\$set\":{\"gender\":\"male\"}}" http://localhost:3000/collectionapi/players/c4acddd1-a504-4212-9534-adca17af4885
With this parameter: ?callback=0
it will return a JSONObject like {status: success}
instead of updated record:
$ curl -H "X-Auth-Token: 97f0ad9e24ca5e0408a269748d7fe0a0" -X PUT -d "{\"\$set\":{\"gender\":\"male\"}}" http://localhost:3000/collectionapi/players/c4acddd1-a504-4212-9534-adca17af4885?callback=0
Delete a record:
$ curl -H "X-Auth-Token: 97f0ad9e24ca5e0408a269748d7fe0a0" -X DELETE http://localhost:3000/collectionapi/players/c4acddd1-a504-4212-9534-adca17af4885
Advanced Features
Handle all requests by yourself
The use case is only for that you want to handle POST request by yourself and don't allow all other requests.
The v0.2.1+
expose an JSONObject returnObject
, which can take some information back to package, then return to user.
The returnObject
look like this:
var returnObject = {
success: false,
statusCode : undefined,
body: undefined
};
If you really want to handle requests by yourself, you need always return true
,
and set returnObject.success = true;
,
then properly set statusCode
and body
.
But you need maintain your Collection(s) manually, don't, never forget this!
There is a simple demo to for handle all requests in application level.
It uses _del
to indicate whether a record was deleted, so you would never lose any data:
https://github.com/xcv58/meteor-collectionapi-demo/blob/cf233f31d973191e6cd4510ed5e017ad695b33f8/server/restful.js#L36
But nothing comes for free, you may face some performance issue. You can move deleted records to another collection, if performance does matter.
Example for handle POST:
POST: function(obj, requestMetadata, returnObject) {
var hasId = obj.hasOwnProperty('id');
if (hasId) {
// insert obj to your collection!
returnObject.success = true;
returnObject.statusCode = 201;
returnObject.body = {
method: 'POST',
obj: obj
};
} else {
returnObject.success = true;
returnObject.statusCode = 500;
returnObject.body = {error: 'no id'};
}
return true;
}
Below is for v0.2.0
to handle POST
request:
For example, you want to split one API path requests to different Collections, the package can't do this. But you can solve it in application level. You should use below code to tell package don't do anything about the passed Collection. That's why all other requests doesn't support yet: the passed Collection (Players) doesn't have any data.
Players = new Meteor.Collection("players");
if (Meteor.isServer) {
Meteor.startup(function () {
// All values listed below are default
collectionApi = new CollectionAPI({
authToken: undefined, // Require this string to be passed in on each request
apiPath: 'collectionapi', // API path prefix
standAlone: false, // Run as a stand-alone HTTP(S) server
allowCORS: false, // Allow CORS (Cross-Origin Resource Sharing)
sslEnabled: false, // Disable/Enable SSL (stand-alone only)
listenPort: 3005, // Port to listen to (stand-alone only)
listenHost: undefined, // Host to bind to (stand-alone only)
privateKeyFile: 'privatekey.pem', // SSL private key file (only used if SSL is enabled)
certificateFile: 'certificate.pem', // SSL certificate key file (only used if SSL is enabled)
timeOut: 120000
});
// Add the collection Players to the API "/players" path
collectionApi.addCollection(Players, 'players', {
// All values listed below are default
authToken: undefined, // Require this string to be passed in on each request
methods: ['POST'], // Allow creating, reading, updating, and deleting
before: { // This methods, if defined, will be called before the POST/GET/PUT/DELETE actions are performed on the collection.
// If the function returns false the action will be canceled, if you return true the action will take place.
POST: undefined, // function(obj, requestMetadata, returnObject) {do everything you wanna; returnObject.success = true; returnObject.statusCode = 201; returnObject.body = {"satus": "success"}; return true;},
// You must return true and set returnObject.success = true, if you want to return the statusCode and body to client! If you return false it will works like ordinary api.
},
after: { // This methods, if defined, will be called after the POST/GET/PUT/DELETE actions are performed on the collection.
// Generally, you don't need this, unless you have global variable to reflect data inside collection.
// The function doesn't need return value.
POST: undefined, // function() {console.log("After POST");},
}
});
// Starts the API server
collectionApi.start();
});
}
Custom Authenticate Function
Despite static authToken, you may need more flexible authenicate approach that you can fully control. So it comes!
You need implement the authenticate
function in collectionApi.addCollection
:
authenticate: function(token, method, requestMetadata) {
console.log("authen");
console.log("token: " + token);
console.log("method: " + method);
console.log("requestMetadata: " + JSON.stringify(requestMetadata));
if (token === undefined) {
return false;
}
if (token === "97f0ad9e24ca5e0408a269748d7fe0a0") {
return false;
}
return true;
},
So the package can give all you need for authentication for every request.
You can authenticate by yourself,
such as allow all POST
and GET
requests even without a authToken
,
allow only PUT
and DELETE
requtests with valid authToken
.
Other use case may be combining the authentication with your existed user system, so that you can assign unique permission for different users.
The arguments token
, method
, and requestMetadata
represent
authen token client provide, request method, and JSONObject contains url metadata respectively.
For example, a request:
$ curl -H "X-Auth-Token: 97f0ad9e24ca5e0408a269748d7fe0a0" http://localhost:3000/collectionapi/players/id/a/b/c\?x\=1\&y\=2\&c\=3
should have output like:
I20150312-11:50:33.222(-4)? token: 97f0ad9e24ca5e0408a269748d7fe0a0
I20150312-11:50:33.222(-4)? method: GET
I20150312-11:50:33.222(-4)? requestMetadata: {"collectionPath":"players","collectionId":"id","fields":["a","b","c"],"query":{"x":"1","y":"2","c":"3"}}
Note that the authenticate function
is optional, and the authToken
you defined in
new CollectionAPI
or collectionApi.addCollection
still work and have higher priority.
So the authentication is hierarchical system.
If you don't need global/static authToken
, just ignore them or set it to undefined
.