47

How would you go about creating a restful web service using Meteor. I would like to create apps in Appcelerator that hook into the same backend.

Can Meteor solve this problem?

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
Andrew Zielinski
  • 495
  • 1
  • 4
  • 4
  • 3
    As of 2015, look at [Gadi's answer](http://stackoverflow.com/a/22601617/1269037) for the Meteorpedia entry on REST APIs, and at [krose's answer](http://stackoverflow.com/a/27828110/1269037) comparing REST API packages. Discussion for folding REST APIs into core is [on Hackpad](https://meteor.hackpad.com/Meteor-Hack-Week-REST-APIs-with-Meteor-XK2NNXqhUvj). – Dan Dascalescu Apr 28 '15 at 22:19
  • 2
    @andrew-zielinski would you consider marking a more recent answer as correct? You current selected one is completely outdated and confusing for people new to the subject (like me). Usually I don't scroll down further to read other answers but luckily in this case I discovered Dan's solution and Gadi's answer. Meteor is way further advance now. Thanks – a4xrbj1 Aug 21 '15 at 10:17

9 Answers9

35

I did a full write-on on this in Meteorpedia:

http://www.meteorpedia.com/read/REST_API

The post reviews all 6 options for creating REST interfaces, from highest level (e.g. smart packages that handle everything for you) to lowest level (e.g. writing your own connectHandler).

Additionally the post covers when using a REST interface is the right or wrong thing to do in Meteor, references Meteor REST testing tools, and explains common pitfalls like CORS security issues.

gadicc
  • 1,431
  • 15
  • 16
  • Would you consider adding my package to that write-up? I just published it, and it was inspired by RestStop2 and built with Iron Router: https://github.com/krose72205/meteor-restivus. I actually found RestStop2 through your article, so thanks! – kahmali Jan 05 '15 at 08:36
  • @krose, sure, the "write-up" is just a page on the wiki... editable by anyone :) – gadicc Feb 07 '15 at 13:03
  • Oh, awesome! I'll add it there when I get a chance. Thanks again for your work on Meteorpedia. It's an awesome resource! – kahmali Feb 07 '15 at 15:41
  • thanks for letting me know, back up! hope all the info is still relevant today. – gadicc Oct 13 '17 at 11:05
22

I originally answered this question here, but to recap:

For adding RESTful methods on top of your data, look into the Collection API written for Meteor:

https://github.com/crazytoad/meteor-collectionapi

As for authentication for accessing the database, take a look at this project:

https://github.com/meteor/meteor/wiki/Getting-started-with-Auth

Both are definitely infantile in development, but you can create a RESTful API and integrate it with a mobile native client pretty easily.

Community
  • 1
  • 1
isyi
  • 1,282
  • 1
  • 11
  • 11
  • 5
    Meteor supports auth natively now; any chance to edit your answer? – Dan Dascalescu Nov 12 '12 at 10:26
  • 5
    Since [my edit](http://stackoverflow.com/revisions/11755233/2) was reversed by @StephanMuller, be aware that the answer as it stands now (June 9, 2015), is completely useless. The Collection API package linked in it has been abandoned for years, and the Meteor wiki guide on implementing Auth has been obsoleted since 2012. The link even redirects away from it. But hey, we have [moderation rules to enforce on SO](http://stackoverflow.com/questions/4652734/return-html-from-a-user-selected-text/4652831?noredirect=1#comment49357917_4652831)! – Dan Dascalescu Jun 09 '15 at 11:13
  • 1
    @StephanMuller Can you please explain why you removed Dan's edit? The answer as it stands is completely wrong, so why leave it with inaccurate information as the most upvoted answer? This can be very misleading for folks that falsely assume that the SO voting and moderating systems work effectively. – kahmali Sep 07 '15 at 03:27
  • 2
    @krose it changes the author's original intent, which is one of the reasons SO offers as a reject reason when reviewing edits. An update like the one he posted should be placed in a comment and/or a new answer. – Stephan Muller Sep 07 '15 at 10:57
  • 1
    @StephanMuller You completely miss the point. Dan requested the author edit this inaccurate information over two years ago. The author never responded. So Dan took the (awesome) initiative of updating the answer himself with more accurate information. Vast improvements have been made for implementing REST in Meteor in the past 2 years. The accepted answer is no longer an answer at all and has a rebuttal by a member of the Meteor team with more upvotes than any answer here. But instead of having moderators focused on curating the best answers, we have folks like you and Bill the Lizard. Sigh. – kahmali Sep 08 '15 at 11:03
  • 1
    @krose You seem to miss the point as well, I didn't invent the rules but I do try to enforce them when I come across something I think doesn't adhere. After your question I checked with a bunch of fellow 10k+ users in chat to make sure that I didn't make a bad call when reverting the edit, and they agreed that my edit was warranted. If you still have problems with it I suggest starting a Meta discussion about it. Saying stuff like 'we have folks like you' isn't going to help your case. – Stephan Muller Sep 09 '15 at 09:53
17

I know this is an old thread, but in case anyone stumbles across it, I published a package for writing REST APIs in Meteor 0.9.0+:

https://github.com/kahmali/meteor-restivus

It was inspired by RestStop2 and built with Iron Router's server-side routing. In my not-so-humble opinion, it's a better solution than anything posted here thus far.

UPDATE: To clarify why I think it's a "better" solution than those mentioned, I'll just point out the differences between each:

CollectionAPI:
CollectionAPI is limited to exposing very basic CRUD operations on your collections. For my use, which is consuming the REST API in mobile apps, it can be extremely wasteful to send down entire documents, and most of the time I need to do some additional processing of data (for instance, sending a Google Cloud Message in a REST endpoint for adding a friend, but only if the friend is successfully added). CollectionAPI gives you a hook that runs before the endpoint is executed, but from what I understand there is nothing immediately before the response, so you have no way of modifying the data that is returned. For authentication, CollectionAPI allows you to define an authToken that must be passed with each request. This acts more like a traditional api key, as it appears to be hard-coded into your app, and would therefore be the same for every user.

Restivus, since it is not limited to automated work on collections, gives you complete control over your endpoints. It now provides all the functionality included in Collection API. It supports user authentication and role permissions as well, so you can identify the user making the request (and easily access that user from within authenticated endpoints). It provides a login and logout endpoint as well to assist with that. I will provide a code example for Restivus at the end.

HTTP.publish:
From what I understand, this is similar to CollectionAPI in that it is limited to exposing basic CRUD operations on collections. This one is more specifically tied to Meteor's publishing, and allows you use a publish function for handling GET requests. I'm confused by the documentation, but it may or may not have some basic authentication available. I haven't used this before, but I'm not a big fan of the API for it, which feels a bit clunky. Once I'm publishing more extensively I'll try to revisit it. The same team has another package called HTTP.methods which doesn't give you the access to the publish functions, but has a similar api to Restivus and, at the time, similar functionality.

Restivus is "better" because it doesn't limit you to using your publish functions, and therefore allows for a much finer-grained control over your endpoints. If you are just looking to expose your publish functions to an external API, I would recommend you stick with HTTP.publish. Restivus also has a simpler API and supports the HTTP PATCH method (which no other package seems to acknowledge exists). Their HTTP.methods package is pretty similar to Restivus, except it lacks PATCH support, and although it offers some basic authentication, I believe you only have the ability to make all endpoints authenticated, or none. Restivus will allow you to control that on a per-endpoint (not just per-route) level. Role permissions (e.g., user, admin) on endpoints are also available on Restivus, but I don't see anything about that for HTTP.methods.

Meteor Router:
This has been deprecated in favor of Iron Router, please see below.

Iron Router:
Iron Router is awesome, but it is not specifically designed for building REST APIs. Recently they added functions corresponding to the HTTP methods (GET, POST, etc.), but they don't support any form of authentication, and all you have access to is the lower-level Node request and response objects, so you'll be forced to learn how to work with those. Once you do, you'll find that there is some repetitive work to be done in each endpoint, like creating responses with the proper headers and response codes. You'll also have to worry about CORS compliance if your API is being consumed from the browser.

Restivus is actually built on top of Iron Router, and provides a layer of authentication on endpoints. It also abstracts away the need for direct interaction with the Node request and response objects, although they're still there in case we've missed anything. So it's using all the awesomeness of Iron Router with a higher-level API for your coding pleasure. Restivus is great if you're already using Iron Router, since it won't add any additional dependency.

RestStop2:
I was actually using RestStop2 in a project I'm working on when it was deprecated in favor of Iron Router. They had solid documentation, and an API I preferred above the others. Per their suggestion, I built a new package on top of Iron Router, which is very much inspired by RestStop2. Restivus is now being endorsed on the RestStop2 GitHub page, so I think they agree that it's a worthy replacement.

Here's a little code snippet from the Quick Start section of the Restivus docs:

if(Meteor.isServer) {
  Meteor.startup(function () {
    // Global configuration
    Restivus.configure({
      useAuth: true,
      prettyJson: true
    });

    // Generates: GET, POST on /api/users and GET, DELETE /api/users/:id for
    // Meteor.users collection
    Restivus.addCollection(Meteor.users, {
      excludedEndpoints: ['deleteAll', 'put'],
      routeOptions: {
        authRequired: true
      },
      endpoints: {
        post: {
          authRequired: false
        },
        delete: {
          roleRequired: 'admin'
        }
      }
    });

    // Maps to: POST /api/articles/:id
    Restivus.addRoute('articles/:id', {authRequired: true}, {
      post: {
        roleRequired: ['author', 'admin'],
        action: function () {
          var article = Articles.findOne(this.urlParams.id);
          if (article) {
            return {status: "success", data: article};
          }
          return {
            statusCode: 400,
            body: {status: "fail", message: "Unable to add article"}
          };
        }
      }
    });
  });
}
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
kahmali
  • 557
  • 6
  • 10
  • mind improving your answer (and also selling it a bit more) to state why it's better than the rest? – dayuloli Jan 12 '15 at 15:36
  • @dayuloli: Sorry for my initial laziness. I updated my post. If you need me to clarify anything just let me know. – kahmali Jan 12 '15 at 18:28
12

Anyone stumbling across this now (2013+), checkout the Meteor Router smart package, which provides methods for server side routing useful in creating RESTful interfaces.

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

To assist you in future searches, be sure to take a look at https://atmosphere.meteor.com - a smart package repository. And Meteorite is a pretty handy CLI tool for version and package management.

papercowboy
  • 3,369
  • 2
  • 28
  • 32
4

The most elegant solution appears to be HTTP.publish. Rather than invent a new API like the others, it simply adds the HTTP protocol to the existing Meteor publish interface. This means, for example, that Meteor.allow and Meteor.deny work automatically for HTTP as well as DDP.

Example:

If handed a collection and a publish function the HTTP.publish will mount on the following URLs and methods:

GET - /api/list - all published data
POST - /api/list - insert a document into collection
GET - /api/list/:id - find one published document
PUT - /api/list/:id - update a document
DELETE - /api/list/:id - remove a document

myCollection = new Meteor.Collection('list');

// Add access points for `GET`, `POST`, `PUT`, `DELETE`
HTTP.publish(myCollection, function(data) {
  // this.userId, this.query, this.params
  return myCollection.find({});
});

It does not yet handle authentication completely.

Community
  • 1
  • 1
David Braun
  • 5,573
  • 3
  • 36
  • 42
  • I don't understand your comment. That's a "HTTP request API", whereas we're talking about exposing a REST service. – David Braun Sep 27 '14 at 02:02
2

I suppose you probably could create a RESTful service using Meteor, but it's not really what the framework is intended for -- one of the main benefits of Meteor is tight interaction between the client and the server, and a web service doesn't have a client side. I'd recommend looking into either writing a web service back end in node.js on its own or something like https://github.com/intridea/grape if you like Ruby.

Patsy Issa
  • 11,113
  • 4
  • 55
  • 74
Masonoise
  • 1,573
  • 3
  • 14
  • 28
  • 45
    Meteor's intended for this. It's just not written yet :) It's quite natural to map queries and mutations on a `Meteor.Collection` to a REST endpoint that clients written in any technology can call. – debergalis Apr 14 '12 at 22:09
  • 2
    Awesome. Any idea when this functionality is coming? :) – Andrew Zielinski Apr 14 '12 at 23:28
  • Agreed, this is great to hear, and it does make a lot of sense. It's obviously pretty natural to build an API layer where only one use is for the web UI, but the close tie between UI and server seems to be Meteor's sweet spot right now. Looking forward to seeing the evolution. – Masonoise Apr 16 '12 at 03:08
2

Yes, you can expose REST endpoints with Meteor using the private API. The functionality will become public soon, but in the meantime, see Can I mount another route handler through ____meteor_bootstrap____.app?.

Community
  • 1
  • 1
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
2

I know this is an old topic, but instead of using any external package, you can use the Meteor WebApp package: https://docs.meteor.com/packages/webapp.html.

Hope it helps!

1

I thought I would update the conversation for 2014. I still haven’t found the perfect way to implement REST services in Meteor and I’m hoping someone can point me in another direction to investigate. I’ve tested 3 projects and each have their drawbacks:

meteor-router I worked with meteor-router but the github page says it will only be fixing bugs going forward and to use Iron Router on all new projects. I’m still considering using this since if it works for me as-is then upgrades aren’t necessary except for some type of authentication.

iron-router I have a simple example service built using Iron Router but it appears to support REST services even less than meteor-router and causes the server to crash if someone posts invalid json to rest endpoint.

meteor-collectionapi Exposes a REST api for basic CRUD operations are support but it doesn’t appear to support queries other than by id.

Matthew
  • 49
  • 1
  • 7
  • 1
    Please check out my answer below and let me know if that package is suitable for your REST API needs. – kahmali Jan 05 '15 at 09:40