DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Why Mocking Sucks
  • How to Enhance the Performance of .NET Core Applications for Large Responses
  • Automatic 1111: Adding Custom APIs
  • Create Proxy Application for Mule APIs

Trending

  • Proactive Security in Distributed Systems: A Developer’s Approach
  • How To Build Resilient Microservices Using Circuit Breakers and Retries: A Developer’s Guide To Surviving
  • Tired of Spring Overhead? Try Dropwizard for Your Next Java Microservice
  • How to Use AWS Aurora Database for a Retail Point of Sale (POS) Transaction System
  1. DZone
  2. Data Engineering
  3. Databases
  4. Integrating External APIs into your Meteor.js Application

Integrating External APIs into your Meteor.js Application

By 
Stephan Hochhaus user avatar
Stephan Hochhaus
·
May. 15, 15 · Tutorial
Likes (0)
Comment
Save
Tweet
Share
39.9K Views

Join the DZone community and get the full member experience.

Join For Free

Meteor itself does not rely on REST APIs, but it can easily access data from other services. This article is an excerpt from the book Meteor in Action and explains how you can integrate third-party data into your applications by accessing RESTful URLs from the server-side.

Many applications rely on external APIs to retrieve data. Getting information regarding your friends from Facebook, looking up the current weather in your area, or simply retrieving an avatar image from another website – there are endless uses for integrating additional data. They all share a common challenge: APIs must be called from the server, but an API usually takes longer than executing the method itself. You need to ensure that the result gets back to the client – even if it takes a couple of seconds. Let’s talk about how to integrate an external API via HTTP.

Based on the IP address of a visitor, you can tell various information about their current location, e.g., coordinates, city or timezone. There is a simple API that takes an IPv4 address and returns all these tidbits as a JSON object. The API is called Telize. 

Making RESTful calls with the http package 

In order to communicate with RESTful external APIs such as Telize, you need to add the http package: 

meteor add http 

While the http package allows you to make HTTP calls from both client and server, the API call in this example will be performed from the server only. Many APIs require you to provide an ID as well as a secret key to identify the application that makes an API request. In those cases you should always run your requests from the server. That way you never have to share secret keys with clients. 

Let's look at a graphic to explain the basic concept.


A user requests location information for an IP address (step 1). The client application calls a server method called geoJsonforIp (step 2) that makes an (asynchronous) call to the external API using the HTTP.get() method (step 3). The response (step 4) is a JSON object with information regarding the geographic location associated with an IP address, which gets sent back to the client via a callback (step 5). 

Using a synchronous method to query an API 

Let’s add a method that queries telize.com for a given IP address as shown in the following listing. This includes only the bare essentials for querying an API for now. Remember: This code belongs in a server-side only file or inside a if (Meteor.isServer) {} block.

Meteor.methods({
  // The method expects a valid IPv4 address
  'geoJsonForIp': function (ip) {
    console.log('Method.geoJsonForIp for', ip);
    // Construct the API URL
    var apiUrl = 'http://www.telize.com/geoip/' + ip;
    // query the API
    var response = HTTP.get(apiUrl).data;
    return response;
  }
});

Once the method is available on the server, querying the location of an IP works simply by calling the method with a callback from the client: 

Meteor.call('geoJsonForIp', '8.8.8.8', function(err,res){ 
  console.log(res);
});

While this solution appears to be working fine there are two major flaws to this approach: 

  1. If the API is slow to respond requests will start queuing up.
  2. Should the API return an error there is no way to return it back to the UI. 

To address the issue of queuing, you can add an unblock() statement to the method:

this.unblock(); 

Calling an external API should always be done asynchronously. That way you can also return possible error values back to the browser, which will solve the second issue. Let’s create a dedicated function for calling the API asynchronously to keep the method itself clean.

Using an asynchronous method to call an API

The listing below shows how to issue an HTTP.get call and return the result via a callback. It also includes error handling that can be shown on the client. 

var apiCall = function (apiUrl, callback) {
  // try…catch allows you to handle errors 

  try {
    var response = HTTP.get(apiUrl).data;
    // A successful API call returns no error 
    // but the contents from the JSON response
    callback(null, response);
  } catch (error) {
    // If the API responded with an error message and a payload 
    if (error.response) {
      var errorCode = error.response.data.code;
      var errorMessage = error.response.data.message;
    // Otherwise use a generic error message
    } else {
      var errorCode = 500;
      var errorMessage = 'Cannot access the API';
    }
    // Create an Error object and return it via callback
    var myError = new Meteor.Error(errorCode, errorMessage);
    callback(myError, null);
  }
}

Inside a try…catch block, you can differentiate between a successful API call (the try block) and an error case (the catch block). A successful call may return null for the error object of the callback, an error will return only an error object and null for the actual response. 

There are different types of errors and you want to differentiate between a problem with accessing the API and an API call that got an error inside the returned response. This is what the if statement checks for – in case the error object has a response property both code and message for the error should be taken from it; otherwise you can display a generic error 500 that the API could not be accessed.

Each case, success and failure, returns a callback that can be passed back to the UI. In order to make the API call asynchronous you need to update the method as shown in the next code snippet. The improved code unblocks the method and wraps the API call in a wrapAsync function. 

Meteor.methods({
  'geoJsonForIp': function (ip) {
    // avoid blocking other method calls from the same client
    this.unblock();
    var apiUrl = 'http://www.telize.com/geoip/' + ip;
    // asynchronous call to the dedicated API calling function
    var response = Meteor.wrapAsync(apiCall)(apiUrl);
    return response;
  }
});

Finally, to allow requests from the browser and show error messages you should add a template similar to the following code. 

<template name="telize">
  <p>Query the location data for an IP</p>
  <input id="ipv4" name="ipv4" type="text" />
  <button>Look up location</button>
  <!-- set the data context -->
  {{#with location}}
    <!-- if location has an error property, display it -->
    {{#if error}}
      <p>There was an error: {{error.errorType}} {{error.message}}!</p>
    {{else}}
      <p>The IP address {{location.ip}} is in {{location.city}}
         ({{location.country}}).</p>
    {{/if}} 
  {{/with}}
</template> 

A Session variable called location is used to store the results from the API call. Clicking the button takes the content of the input box and sends it as a parameter to the geoJsonForIp method. The Session variable is set to the value of the callback. 

This is the required JavaScript code for connecting the template with the method call:

Template.telize.helpers({
  location: function () {
    return Session.get('location');
  }
});

Template.telize.events({
  'click button': function (evt, tpl) {
    var ip = tpl.find('input#ipv4').value;
    Meteor.call('geoJsonForIp', ip, function (err, res) {
      // The method call sets the Session variable to the callback value
      if (err) { 
        Session.set('location', {error: err});
      } else {
        Session.set('location', res);
        return res;
      }
    });
  }
}); 

As a result you will be able to make API calls from the browser just like in this figure:


And that’show to integrate an external API via HTTP! 

application API

Opinions expressed by DZone contributors are their own.

Related

  • Why Mocking Sucks
  • How to Enhance the Performance of .NET Core Applications for Large Responses
  • Automatic 1111: Adding Custom APIs
  • Create Proxy Application for Mule APIs

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!