- Published on
Creating a weather app with IP geolocation API in Node.js
In this blog, we will learn how to integrate two APIs in a single project and make them talk to each other. We will create a Node.js app that will use an IP geolocation API and a weather API. I believe many developers created a weather app as one of their learning projects. Today, we can move a bit forward and add another API to make the weather app smarter.
In a typical weather app, you’d need to enter your location, but in our project, we will find out the current location using an IP geolocation API.
Below we have a basic structure of our app. We can see that there are three important steps involved:
- Getting device’s IP address
- Calling IP geolocation API with the IP address as a parameter and saving the returned object
- Calling weather API with state and city as parameters and outputting the result to the user
Setting up the server
We are going to use Node.js and Express to create our app.
mkdir geo-wea
cd geo-wea
npm init -y
npm i express
We will use modern ES Modules. For Node.js to handle them correctly, go to package.json
file and add "type": "module"
. The result should look something like this:
{
"name": "geo-wea",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.1"
}
}
Create index.js
file with the following code:
import express from 'express';
const app = express();
app.listen(3000, () => {
console.log('Server listening on 3000');
});
Now to check if everything works, run the application:
node index.js
Extracting device's IP address
Every request a device sends to a server will always have an IP address of the device.
Now we need to read an IP address of the device connecting to our application. Express can read it from the incoming connection. Typically, our application will run behind a reverse proxy, which will pass the original IP address in HTTP headers. Express won’t read this header by default, but you can instruct it to trust the IP address passed in headers from the proxy:
app.set('trust proxy', true);
To learn more, check Public vs. Private IP Address: What's the Difference.
We can read the IP address from the ip
property of the incoming request (req
). Replace index.js
with the following code:
import express from 'express';
const app = express();
app.set('trust proxy', true);
app.get('/', async (req, res) => {
const ip = req.ip;
res.send(ip);
});
app.listen(3000, () => {
console.log('Server listening on 3000');
});
Now, when you visit your application running locally or on CodeSandbox, you should see your IP address.
Note: I am using CodeSandbox for this example because if I run the server on my PC, it would see me connecting from localhost
or local IP address.
Installing Superface SDK
I am going to use Superface for API integration as it makes the integration super easy. Since we will use two APIs in this project, normally I’d have to go through two different API docs, but with the mighty power of Superface, I don’t need to. Learn one to conquer all.
First, install Superface OneSDK in your app:
npm i @superfaceai/one-sdk@2
We will ue the following use cases from the Superface catalog: IP geolocation lookup and Current Weather In City.
IP geolocation API
This allows us to identify the country, state, and city based on the IP address of your device. To find out more about IP geolocation, check my previous article.
Now we have to pick a provider to use. I will use ipdata. Create an account on ipdata.co to get your API key.
Back in Superface, select ipdata
provider, copy and paste the code from the example into your index.js
file. Replace <your apikey from ipdata>
with the API key you got from ipdata and the public IP address you into the ipAddress
property.
Here is the resulting code:
import express from 'express';
import { SuperfaceClient } from '@superfaceai/one-sdk';
const app = express();
app.set('trust proxy', true);
const sdk = new SuperfaceClient();
async function run(ip) {
// Load the profile
const profile = await sdk.getProfile('address/ip-geolocation@1.0.1');
// Use the profile
const result = await profile.getUseCase('IpGeolocation').perform(
{
ipAddress: ip,
},
{
provider: 'ipdata',
security: {
apikey: {
apikey: '<your apikey from ipdata>',
},
},
}
);
// Handle the result
try {
const data = result.unwrap();
return data;
} catch (error) {
console.error(error);
}
}
app.get('/', async (req, res) => {
res.send(await run(req.ip));
});
app.listen(3000, () => {
console.log('SERVER RUNNING AT PORT 3000');
});
Now just run your app with node index.js
, visit localhost:3000
, and you should see a result:
Weather API
Moving on to the third step: calling the weather API with the data returned by IP geolocation API. This API will return to us the current weather in the city we provide. Find Get Current Weather In City in Superface catalog and choose a provider. For this tutorial, I will use openweathermap
.
Create an account on OpenWeatherMap.
Same as before, copy and paste the code from the example. Replace <your apikey from openweathermap>
with the API key you got from OpenWeatherMap and pass in the city you got from the call to Geocoding API. Rename the run
function, to something more descriptive. Here’s the resulting code:
import express from 'express';
import { SuperfaceClient } from '@superfaceai/one-sdk';
const app = express();
app.set('trust proxy', true);
const sdk = new SuperfaceClient();
async function findCity(ip) {
// Load the profile
const profile = await sdk.getProfile('address/ip-geolocation@1.0.1');
// Use the profile
const result = await profile.getUseCase('IpGeolocation').perform(
{
ipAddress: ip,
},
{
provider: 'ipdata',
security: {
apikey: {
apikey: '9a511b6fc8334e1852cfbbd4ff3f1af3c42ed6abc75e96a1648b969a',
},
},
}
);
// Handle the result
try {
const data = result.unwrap();
return data;
} catch (error) {
console.error(error);
}
}
async function weather(city) {
// Load the profile
const profile = await sdk.getProfile('weather/current-city@1.0.3');
// Use the profile
const result = await profile.getUseCase('GetCurrentWeatherInCity').perform(
{
city: city,
units: 'C',
},
{
provider: 'openweathermap',
security: {
apikey: {
apikey: '9a7c7994ccda87a3f8bb2767d5ca48db',
},
},
}
);
// Handle the result
try {
const data = result.unwrap();
return data;
} catch (error) {
console.error(error);
}
}
app.get('/', async (req, res) => {
try {
let city = await findCity(req.ip);
res.send(await weather(city.addressLocality));
} catch (error) {
console.log(error);
}
});
app.listen(3000, () => {
console.log('SERVER RUNNING AT PORT 3000');
});
Now run your app with node index.js
you should see the result:
You can find the final result on CodeSandbox.