Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Using the HTTP Package

DZone's Guide to

Using the HTTP Package

This article will show you how to use the Meteor HTTP package to make HTTP GET, POST, PUT, and DELETE requests.

· Integration Zone
Free Resource

Build APIs from SQL and NoSQL or Salesforce data sources in seconds. Read the Creating REST APIs white paper, brought to you in partnership with CA Technologies.

This is the first in a guest series from Ryan Glover. This post originally appeared as a snippet on The Meteor Chef, a site dedicated to showing you how to solve day-to-day problems in your Meteor applications.

dribbble_announcement_400x300.png

What We're Going to Learn

In this snippet we're going to learn how to use the Meteor HTTP package to make HTTP requests. We'll learn about the two ways we can use the HTTP package to make GET, POST, PUT, and DELETE requests. We'll also learn how to make synchronous requests on the server.

When we’re building applications on the web, it’s not uncommon to want to access data that lives outside of our application. Sometime’s this data is owned by us, but more often, it’s owned by a third-party. The data we’re after is usually something that will enhance our own application, for example: weather data, posts we’ve made on a social network, or statistical data from the government.

What data we’re after doesn’t really matter. What does matter is how we access that data and make use of it in our own applications.

The HTTP Package

In an effort to simplify the process of making HTTP requests from Meteor applications, the Meteor Development Group offers a package called HTTP. This package can be used to perform a request using any of the standard HTTP methods. As a bonus, too, the package offers a handful of “shorthand” methods for commonly used HTTP methods: GET, POST, PUT, andDELETE.

JSONPlaceholder

For our example, we’re going to be making use of the JSONPlaceholder API which allows us to make real HTTP requests without the potential for destruction. This means we’ll be able to use all of the common methods, but the actions they perform will be dummy actions, or, just for testing. Cool!

Standard HTTP Requests in Meteor

Here’s the standard way of making requests using the HTTP package in Meteor. Pay attention to the syntax here.

HTTP.call( 'METHOD', 'http://url.to/call', { "options": "to set" }, function( error, response ) {
  // Handle the error or response here.
});

First, when we say “standard HTTP requests” we mean using the HTTP.call() method and passing a specific type of method as the first argument. For example, here, we can replace'METHOD' in the example above with GET, POST, PUT, or DELETE. When we do this, Meteor will take that method name and pass it along in the headers of that HTTP request (what the HTTP protocol uses to describe requests and responses between servers).

Next, we pass a URL to actual make our call to. When we’re working with a third-party API, this might look like https://api.website.com/v1/some/endpoint, or, http://website.com/api/v1/some/endpoint. Note: this structure is specific to the third-party application, not our application. When making calls to third-party APIs (i.e. not our application), you will want to reference the URLs outlined in the API documentation for the third-party application.

Third, we pass an object with a set of options. Shown here is just dummy data, not what we’d actually pass. Meteor gives us the following options to pass with our request:

Name Type Accepted How it Works
content String Takes a plain String and sets it on the HTTP request body.
data Object Takes an object, converts it to a string, and sets it on the HTTP request body. Note: this overwrites thecontent field if one is set.
query String Takes a query string like ?key=value&something=else&some=dataand appends it to the URL (e.g.http://website.com/api/v1/endpoint?key=value&something=else&some=data. Note: this overwrites any existing query strings in the URL.
params Object Takes an object and converts it to a query string like ?key=value&something=else&some=data forGETrequests. For POST requests, takes an object, converts it to a string, and sets it on theHTTP request body.
auth String Takes a String with a username and password to use for HTTP basic authentication (e.g.username:password, or,themeteorchef:pizzaparty).
headers Object Takes an Object containing key/value pairs that correspond to HTTP header field names and values.
timeout Number How long in milliseconds (e.g. 1000 for one second) the request should wait for a response from the other server before stopping/failing. Note: no timeout exists by default, so if you don’t set one your request (could) try indefinitely so use caution.
followRedirects Boolean If the request receives an HTTP redirect (e.g. a301, URL moved permanently) in response, determines whether or not it should follow it to the new URL. Note: by default this is true and cannot be set to false on the client.
npmRequestOptions Object

On the server, accepts an

Object

that can be passed as options to be used with the NPM request module. Meteor uses this NPM packageon the server which accepts its own options. Adding this option, here, just defers anything in the object to the request module’s options. Confusing, but handy!

Lastly, we pass a callback function that accepts an error and response argument. Note: if an error occurs, response will be undefined.

CALLS ARE ASYNCHRONOUS WITH A CALLBACK

When we provide a callback as the final argument to our HTTP requests, they will be run asynchronously. If we make our requests without a callback, they will be run synchronously, returning either the error or response back when complete. This applies to the shorthand requests below, too.

Shorthand HTTP Requests in Meteor

In addition to the regular HTTP.call() method, we can all use a handful of shorthand methods that Meteor gives us to simplify calling the more common HTTP methods.

HTTP.get( 'url', { /* options */ }, function() {} );
// Like calling HTTP.call( 'GET', 'url', { /* options */ }, function() {} ); 

HTTP.post( 'url', { /* options */ }, function() {} );
// Like calling HTTP.call( 'POST', 'url', { /* options */ }, function() {} ); 

HTTP.put( 'url', { /* options */ }, function() {} );
// Like calling HTTP.call( 'PUT', 'url', { /* options */ }, function() {} ); 

HTTP.del( 'url', { /* options */ }, function() {} );
// Like calling HTTP.call( 'DELETE', 'url', { /* options */ }, function()

Notice, these are identical to calling the HTTP methods by name as the first parameter in anHTTP.call().

GET Requests

GET requests do exactly what you think they might: get data. When we make an HTTP call on a URL using a GET request, that URL (part of an API) will return to us some sort of data based on the parameters we pass. Note: when we make a GET request, the URL should respond accordingly with data. Let’s see what this looks like using our JSONPlaceholder’s example GETendpoint.

HTTP.call( 'GET', 'http://jsonplaceholder.typicode.com/posts', {}, function( error, response ) {
  if ( error ) {
    console.log( error );
  } else {
    console.log( response );
    /*
     This will return the HTTP response object that looks something like this:
     {
       content: "String of content...",
       data: Array[100], 

Notice that here, our response argument equal to the response object (not raw data). To get access to just our data (usually what we want to do unless there’s a reason to look at the status code or headers) we can call response.data. Nice! Above we’ve called this using theHTTP.call() method, but we could just as easily use HTTP.get() and get the same results.

USING JSON.PARSE

Although we have access to our data in the data field here, we could also use the JSON.parse( response.content ) method, passing our response.content field. This, then, would parse the content string into JSON data.

We can also call GET requests with a set of parameters to narrow down our results.

HTTP.call( 'GET', 'http://jsonplaceholder.typicode.com/posts', {
  params: {
    "id": 5
  }
}, function( error, response ) {
  if ( error ) {
    console.log( error );
  } else {
    console.log( response );
    /*
     This will return the HTTP response object that looks something like this:
     {
       content: "String of content...",
       data: [{
         "body": "The body of the post with the ID 5."
         "id": 5,
         "title": "The title of the post with the ID 5.",
         "userId": 1
       }],
       headers: {  Object containing HTTP response headers }
       statusCode: 200
     }
    */
  }
});

See that here, instead of getting back a massive array of results, we get back an array with a single item because we specified that we only want the items where the id field is equal to 5.

POST Requests

POST requests are designed to send or post some sort of data. POSTs are generally reserved for some sort of creation: a new document or a new message, for example. These are a little more complicated than GET requests because we’re usually expected to pass some data along. Note: POST requests usually expect to find the data to post in the request objects body field.

HTTP.call( 'POST', 'http://jsonplaceholder.typicode.com/posts', {
  data: {
    "title": "Title of our new post",
    "body": "Body of our new post",
    "userId": 1337
  }
}, function( error, response ) {
  if ( error ) {
    console.log( error );
  } else {
    console.log( response );
    /*
     This will return the HTTP response object that looks something like this:
     {
       content: "String of content...",
       data: {
         "id": 101,
         "title": "Title of our new post",
         "body": "Body of our new post",
         "userId": 1337
       },
       headers: {  Object containing HTTP response headers }
       statusCode: 201
     }
    */
  }
});

Here we get back acknowledgement that our new post was created (when we say post here we mean a blog post, the example of choice given to us by JSONPlaceholder) in the form of an object with the same parameters as the object we set in our data option, along with a new idfield equal to the id where our new post lives in the remote database.

PUT Requests

PUT requests are designed to update or put some new data into an existing document. PUTs are generally only limited to updating existing information, however, some APIs may design aPUT to behave more like an upsert (i.e. if a document doesn’t exist to update it will try to create one). This on a case-to-case basis, though, so don’t bet on it behaving that way.

HTTP.call( 'PUT', 'http://jsonplaceholder.typicode.com/posts/1', {
  data: {
    title: "Title of our updated post.",
    body: "Body of our updated post."
  }
}, function( error, response ) {
  if ( error ) {
    console.log( error );
  } else {
    console.log( response );
    /*
     This will return the HTTP response object that looks something like this:
     {
       content: "String of content...",
       data: {
         body: "Body of our updated post.",
         id: 1,
         title: "Title of our updated post.",
         userId: 1
       },
       headers: {  Object containing HTTP response headers }
       statusCode: 200
     }
    */
  }
});

Here, we pass the id of the document we want to update in the URL and then in the dataobject, pass the updates we want to make to that document. Note: some APIs may require you to pass the ID of the document you want to update in the data field (which gets placed in the request body). This is more common than in the URL, but make sure to check documentation for the API to be certain.

As we might expect, we get back an object containing our body and title fields equal to our new values along with the id of the document updated and the userId doing the update.

USING API KEYS & AUTHENTICATION

So far none of our requests have used any form of authentication (and won’t need to). If you’re working with an API that does use API keys or some other form of authentication, you will need to pass that data along with each request. Depending on the type of this request, this may need to be passed with your params or data fields (which are passed to the query string and request body, respectively), or, in the headers object.

This is something that depends on the API, so make sure to read their docs to see where your authentication credentials should be passed.

DELETE Requests

The request method we’ll cover, DELETE, does exactly what you’d expect: deletes a document.

HTTP.call( 'DELETE', 'http://jsonplaceholder.typicode.com/posts/1', {
  data: {
    title: "Title of our updated post.",
    body: "Body of our updated post."
  }
}, function( error, response ) {
  if ( error ) {
    console.log( error );
  } else {
    console.log( response );
    /*
     This will return the HTTP response object that looks something like this:
     {
       content: "{}",
       data: {},
       headers: {  Object containing HTTP response headers }
       statusCode: 200
     }
    */
  }
});

Interestingly, when we delete a document this API returns a response containing pretty much…nothing! Other APIs, though, might return the ID we deleted or some sort of message acknowledging the delete.

Synchronous HTTP Requests on the Server

In all of these requests we’ve made what are known as asynchronous requests, meaning, we don’t wait for a response from the server to “keep going” with our other code. We technically don’t have any other code here, but if we did it would run automatically whether or not the server we’re making our request to has responded yet. This is generally okay, but there may be some scenarios where you want to make your requests synchronously, meaning no other code is run until the request has been fulfilled and the response has been received.

var response = HTTP.call( 'GET', 'http://jsonplaceholder.typicode.com/posts/1', {} );
console.log( response );

Here, we make the call HTTP.call()without a callback function as the final parameter. Without this, Meteor knows we want to run our request synchronously and will simply return either the error or response from the other server. In the example above, we wouldn’t expect to see ourresponse variable logged to the console until our HTTP.call() was complete and received a response. Keep in mind, we can only do synchronous requests on the server. This will not work on the client.

Takeaways

  • All APIs are different so make sure to review the documentation to understand how requests should be formed.
  • Most APIs will require you to pass some form of authentication (usually an API key or username/password).
  • Experiment with synchronous HTTP calls on the server where blocking behavior could improve the flow of data in your application.

The Integration Zone is brought to you in partnership with CA Technologies.  Use CA Live API Creator to quickly create complete application backends, with secure APIs and robust application logic, in an easy to use interface.

Topics:
meteor ,rest ,api ,http ,json

Published at DZone with permission of Ryan Glover. See the original article here.

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}