Adding web services to Meteor in 2017

I would like to create API endoints to interact with a meteor app.
I read about packages likesimple:rest or restivus, but the development seems to have stopped.

What is the way to go in 2017? Can restify, express or any other npm package be used with meteor?

Good questions. We are facing a similar decision in our open source project.

Our previous work has been with Restivus, but we are currently leaning towards Simple REST for at least a couple of reasons:

  • it leverages methods, publications, and collections directly, which are the standard ways to move data round in Meteor
    • this gives us double incentives to make sure our methods, publications, and collection code (e.g. schema) are well maintained
    • also means we aren’t ‘dragging along’ a REST API that we are not using, which is a major no-no in the API First and Design First APIs philosophies
  • we are fighting with featuritis, feature creep, feature fatigue, etc. in our project a bit, so using a package that explicitly values simplicity seems like a welcome addition.
1 Like

@brylie, but simple rest is an abandoned lib. Have you considered using Express or Restify?

Express or Restify seem to be worth consideration. Are there any examples showing how Express or Restify could be integrated into a Meteor app?

Also, for the project I mentioned earlier, we ended up continuing to work with Restivus.

You can actually use Express with Meteor. Take a look at this - [Meteor + Express] (http://www.mhurwi.com/meteor-with-express/) Integration.

You should cross restify off your list. Restify is intentionally built to be a standalone application framework and does not even integrate with connect or express because it overwrites some of node’s http apis. If you check some of the related issues in restify’s github tracker, you’ll see that the authors are very explicit with their replies to whether restify can be integrated into other express/connect apps, they simply say no and the restify app must be a separate, standalone, headless app.

Both connect and express are very easy with Meteor, though.

1 Like

I was able to get Simple Rest working with Publications and Meteor Methods last night – it was a painless setup.

I haven’t looked deep enough yet, I wonder does Simple Rest only return JSON or could a method return for example a “Stream” that a client could use to render a PDF to the browser?

@serkandurusoy, I’d love to see examples of how you set up your REST routes from your recent project?

Instead of using a lib like Express or Simple Rest,

import express from 'express';

const app = express();
WebApp.connectHandlers.use(Meteor.bindEnvironment(app));
app.post('/', function (req, res) {
  res.send('POST request to the homepage')
})

you just used WebApp and connect, stuff Meteor already comes with out of the box right?

Something like this?

WebApp.connectHandlers.use('/api/whatever', function (req, res) {
  req.on('data', Meteor.bindEnvironment(chunk => {
    const data = JSON.parse(chunk);
    // ... do stuff here
  }));

  res.writeHead(200);
  res.end('OK');
});
2 Likes

Hey @aadams you can indeed use JsonRoutes (one of the simple:rest packages) to write to a stream and send that as a response or anything you want because you have access to the response object, the res part of function(req, res) {} signature.

import { JsonRoutes } from 'meteor/simple:json-routes';
import Excel from 'exceljs';

JsonRoutes.add('get', '/downloadExcel', (req, res) => {
  JsonRoutes.setResponseHeaders({
    'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'Content-Disposition': 'attachment;',
  });
  const wb = new Excel.Workbook();
  wb.addWorksheet(`sheet one`);
  wb
    .xlsx
    .write(res)
    .then(() => JsonRoutes.sendResult(res));
})

I’m glad you found simple:rest easy because it is and it is also very powerful. I doubt you’d have much trouble with it, if at all.

As for using connect without express, an example would be:

import { WebApp } from 'meteor/webapp';
import connectRoute from 'connect-route';
import bodyParser from 'body-parser';

const app = WebApp.connectHandlers;

app.use(bodyParser.urlencoded({ extended: true, limit: '50mb' }));
app.use(bodyParser.json({ limit: '50mb' }));

app.use((req, res, next) => {
  console.log('New request accepted', req);
  next();
});

app.use((req, res, next) => {
  res.setHeader('Content-type', 'application/json');
  res.setHeader('Cache-Control', 'no-store');
  res.setHeader('Pragma', 'no-cache');
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With');
  next();
});

app.use(Meteor.bindEnvironment(connectRoute((router) => {
  router.get('/say/:what', (req, res) => {
    const {
      what,
    } = req.params;
    const response = {
      say: what,
    };
    const prettyResponse = JSON.stringify({
      status: 'success',
      response,
    }, null, 2) 
    res.end(prettyResponse);
  });
})));

Don’t be alarmed by the lines of code, I just wanted to demonstrate to you that you can do anything.

The main difference compared to express is that connect does not have a router out of box, so that’s what I added. Express comes loaded with other stuff like a view/templating engine, which I doubt you’d ever need since all you want is a rest api. Express is more relevant for “web apps” whereas I found Connect capable enough for “rest apis”.

2 Likes

This code you wrote here is amazingly helpful, thank you!

1 Like

@serkandurusoy, I have a question regarding JsonRoutes and Tokens I’d really like to get your take on right here: Meteor REST APIs with JsonRoutes (I didn’t want to take over this thread on side issues)

1 Like

JsonRoutes is an excellent package. It requires a bit more configuration than restivus and some of the other attempts at auto-configured collection APIs. In particular, you’ll need to roll your own authentication. But otherwise, it works great; and provides enough flexibility that you can implement to an API spec from a 3rd party source. We make sure our web services conform to standards specified by the AEGIS Touchstone project; and they regularly are tweaking things like mime-types, schema structure, headers, encryption, response messages, etc. And we’re able to roll with each change, and make sure our implementation of their API spec is in conformance.

2 Likes

@awatson1978 will you take a look at my post here: Meteor REST APIs with JsonRoutes where I ask about security and give me your advice? You say we have to roll our own, does that mean I’m going to have to manually check the token for example?