Making a RESTful application with MeteorJS

Hello all!

I’m fairly new to MeteorJS, so please bear in mind that I do not have much experience.

I’ve come here after unsuccessfully trying to make my MeteorJS application be able to take GET and POST requests. Hopefully I will have better luck here.

Basically, every time I make a GET or POST call (using curl, a Ruby script, and REST Console) I get the HTML code of a blank page back that has full tags but an empty tag. It happens regardless the package that I use (I tried Restivus and Picker).

I posted a more detailed question (with example code) in Stackoverflow, if you need more details.

Has anyone face the same issue before? If so, how did you approach it?

I am open to use another package, but that does not seem to be the issue.

Thank you in advance!

1 Like

It can be a little rough getting going. Here’s an example repo using Iron Router (I haven’t used the others).

https://github.com/AdamBrodzinski/meteor-rest-example

If you download it and run the following commands you’ll get this output (also logs request data)

curl -X GET  'http://localhost:3000/reports/123'

{
  "name": "Bob",
  "age": 21
}

curl -X POST -d 'age=70' 'http://localhost:3000/wrongroute/123'

{
  "error": {
    "type": "invalid_request_error",
    "code": "404",
    "message": "Route not found"
  }
}

curl -X POST -d 'age=70' 'http://localhost:3000/reports/123'

{
  "name": "Bob",
  "age": "70"
}

The main bit is here:

/*global respondWithJson */

// matches /reports/ and id
Router.route('/reports/:id', {where: 'server'})

// create a report
.post(function () {
  var newReport = this.request.body;
  var oldReport = {name: 'Bob', age: 21};

  try {
    // do a fake update and return it
    // use try/catch in case it throws
    newReport = _.extend(oldReport, this.request.body);
    respondWithJson(201, this.response, newReport);
  }
  catch (e) {
    respondWithJson(500, this.response, {error: true});
  }
})


 // retrieve a report
.get(function() {
  var oldReport = {name: 'Bob', age: 21};

  try {
    respondWithJson(201, this.response, oldReport);
  }
  catch (e) {
    respondWithJson(500, this.response, {error: true});
  }
});


2 Likes

Your solution worked, thank you!

I do have some questions about your solution.

First, I see that you have the route.js file in the path server/route/, is that important? Can in be in lib folder?

Second, what is the need of /:id? At no point does the route use id, and for me, it seemed to ignore the routes where I specified :message. It instead went for the route where I only typed Router.route('/newReport/', {where: 'server}).

Third, what is the use of {where: 'server'} if our router file is already in the server folder?

Thank you!!

Sure, route.js could be in lib. I would put the router_config.js file in there as well though. It basically just need to be parsed before the route is called.

:id params are not needed I just wanted to show how you can use the id if you’re fetching a report by id. If you’re using REST then it would be something like GET /reports/1234. If you want it to be optional put a question mark after it like /reports/:id?

You need to specify the where or you’ll end up pulling down the client HTML. Even though it’s in the server file it still thinks it’s a clientside route.

Also you mentioned using /newReport, this works just fine but if you want to stick to REST conventions using a POST /reports/new and then passing in form data for the content is the way to go. Saying that you’ve prob. noticed that my POST call has params 123… this isn’t needed as the report doesn’t exist yet. I meant to use PUT in my example above. Oh well!

However at any rate using newReport works just fine!

Worth watching would be “Teach a Dog to REST”:

2 Likes

You should also check out this package.

1 Like

@jperl ah, didn’t see that one yet!

Yea def. check that package out @sammyis … IR is ok but i’m mainly using it for legacy special case reasons. meteor-rest seems like a much easier way to go (or simple-json at the least).

Good work @sashko !

1 Like

The entire package group seems like an overkill for what I needed. And there seems to be an overlap between simple:rest and simple:json-routes.

However, they do seem way easier to use than iron-router. I’ll keep them in mind in the future.

Thank you @jperl and @SkinnyGeek1010!