Home

Awesome

DEPRECATION NOTICE

Using meteor 0.6.5 or greater? Check out RestStop 2.

.

.

.

.

.

.

NOTE: Current in beta, so use with caution. Things are likely to break or change.

WHAT IT DOES

RESTstop makes it easy to create RESTful APIs built on top of Meteor, for use with legacy systems (or if you're just too lazy to get DDP+SRP working).

It's a psuedo-fork of Meteor Router's, with a few major differences:

INSTALLATION

Install from Meteorite:

[ install meteorite ]
mrt add reststop

Or, install it manually:

cd your-meteor-project
git submodule add git@github.com:gkoberger/meteor-reststop.git packages/reststop

WRITING AN API

Here's some simple API methods:

if (Meteor.isServer) {
  Meteor.RESTstop.configure({use_auth: true});

  Meteor.RESTstop.add('get_user', function() {
    if(!this.user) {
      return {'is_loggedin': false};
    }
    return {
      'is_loggedin': true, 
      'username': this.user.username
    };
  });

  Meteor.RESTstop.add('get_num/:id?', function() {
    if(!this.params.num) {
      return [403, {success: false, message: 'You need a num as a parameter!'}];
    }
    return this.params.num;
  });

  Meteor.RESTstop.add('posts', {require_login: true}, function() {
    var posts = [];
    Posts.find({owner_id: this.user._id}).forEach(function(post) {

      // Modify the post here...

      posts.push(post);
    });
    return posts
  });
}

Configure Options

The following configure options are available:

Options for add()

For Meteor.RESTstop.add, the following options (second parameter) are available:

URL structure

The path is the first parameter of Meteor.RESTstop.add. You can pass it a string or regex.

If you pass it test/path, the full path will be http://yoursite.com/api/test/path.

If you want to pass in parameters, use a :. So, post/:id will match things like api/post/123. You'll be able to access the value using this.params.id.

If you want to make a parameter optional, use ?. So, post/:id? will match both api/post and api/post/123.

If someone accesses an undefined route, by default a 404 and {success: false, message: "API method not found"}. You can overide this by using * as your route, which acts as a catch-all.

What each method gets access to

Returning results

You can return a string:

return "That's current!";

Or, a JSON object:

return {json: 'object'};

Or, include an error code by using an array with the error code as the first element:

return [404, {success: false, message: "There's nothing here!"}];

Or, include an error code AND headers (first and second elements, respectively):

return [404, {"Content-Type": "text/plain"},  {success: false, message: "There's nothing here!"}];

Or, skip using a function at all:

Meteor.RESTstop.add('/404', [404, "There's nothing here!"]);

Using Authentication:

When you log in, you'll get a userId and loginToken back. You must save these and include them with every request. See below for examples.

Accessing Server Methods

You can access server methods using Meteor.RESTstop.apply(this, 'method_name', [..args..]):

result = Meteor.RESTstop.apply(this, 'method_name', [arg1, arg2]);

Or using call:

result = Meteor.RESTstop.call(this, 'method_name', arg1, arg2);

You can also get published data in a similar manner:

result = Meteor.RESTstop.getPublished(this, 'method_name', [arg1, arg2]);
result.fetch() // You'll need to manually fetch the results

If you have use_auth on and the user is authenticated (see above), you'll be able to access this.userId and Meteor.user() as normal.

(Note: This all seems to be working, however it's the hackiest part of this whole package -- be very cautious and test well.)

USING THE API YOU CREATED

The following uses the above code.

Any results specified by RESTstop (mostly errors) will include a JSON object with a boolean named success and a string called message.

Basic usage

We can call our get_num the following way. Note the /api/ in the URL (defined with the api_path option above).

curl --data "num=5" http://localhost:3000/api/get_num/

Or (using the optional :id from the URL):

curl http://localhost:3000/api/get_num/5

Authenticating

If you have use_auth set to true, you now have a /login method that returns a userId and loginToken. You must save these, and include them in subsequent requests.

(Note: Make sure you're using HTTPS, otherwise this is insecure. In an ideal world, this should only be done with DDP and SRP.. but alas, this is an RESTful API.)

curl --data "password=testpassword&user=test" http://localhost:3000/api/login/

The response will look something like this, which you must save (for subsequent requests):

{success: true, loginToken: "f2KpRW7KeN9aPmjSZ", userId: fbdpsNf4oHiX79vMJ}

Usage with logged in users

Since this is a RESTful API (and it's meant to be used by non-browsers), you must include the loginToken and userId with each request.

curl --data "userId=fbdpsNf4oHiX79vMJ&loginToken=f2KpRW7KeN9aPmjSZ" http://localhost:3000/api/posts/

Or, pass it as a header. This is probably a bit cleaner:

curl -H "X-Login-Token: f2KpRW7KeN9aPmjSZ" -H "X-User-Id: fbdpsNf4oHiX79vMJ" http://localhost:3000/api/posts/

THANKS TO

Thanks to the following awesome projects, which I borrowed/stole ideas and code from: