2

I am building a react app, and in it I am retrieving data from a third party site which requires me to send the API key in the header using 'X-Auth-Token'.

Currently I am making this request using fetch() api from the clientside js files. I understand this is bad practice and I should hide my api key, so this is what I am trying to do but am finding it hard to understand how all the components fit together in this puzzle...

I have followed a tutorial and now have a create-react-app project listening locally on port 3000, and an express server (using express.router()) listening locally on port 9000.

I want to make the api request to the third party from the express server, and then send that to the front end.

  1. using express.router(), how would i make a request to a third party that includes my api key, and then send that on to the front end?
  2. when i eventually host this project (i am hosting on heroku), instead of the front end making a fetch request to port9000 to retrieve the data from the express server request, what url should it be listening to? - I think i lack understanding when it comes to this part.
Jonny
  • 593
  • 4
  • 15

2 Answers2

2

You are on point, you should use like a middleman to retrive your data to your frontend. There are couple of implementation of course. Personally I like the serverless approach, using AWS lambda functions for it. But back to your approach. I would retrive the data using probably the axios module, very easy and straightforward. You can pass the x-auth-token header to the instance


const express = require('express');
const axios = require('axios');

const app = express()

const axiosInstance = axios.create({
    baseURL: '<some-domain>',
    headers: { 'X-Auth-Token' : '<some-token>'}
});

app.get('/data', async(req, res, next) => {
    try {
        const response = await axiosInstance.get('/<path>');
        // process your data and send back to the user
    } catch (error) {
        // handle if you got an error
    }
})

It is just a showcase, I assume your application looks different, but I think you got some direction from this snippet.

I would hide the token to an environment variable.

When you deploy your server to heroku you are going to get an url, and in your front-end you can replace the url easily and deploy it.

Sándor Bakos
  • 213
  • 4
  • 8
  • Thank you for your answer. I am not familiar with Axios but the concept seems to make sense. Can I just ask - the baseURL is presumably the url of the third party API. '/data' - what exactly does this refer to and the same with '/'? – Jonny Aug 08 '19 at 11:00
  • Yes the basURL is the url of the third party API. `axisosInstace.get(/)` the here is the 3rd party path, for example if you need to reach additional path in the request, like https://some-data.com/newdata --> here is the `/newdata` is the path. If you don't have a path just leave as '/'. The `app.get('/data` is the endpoint for your server, your react app calling in your localhost `localhost:9000/data`, but as I mentioned I don't know your code it can be anything else. – Sándor Bakos Aug 08 '19 at 11:08
  • Thanks a lot for all your help. I actually was using the express-generator which was complete overkill and kept throwing up errors, i think I was doing something wrong with the routing but i couldn't work it out. I replaced that with a single app.js file and included this method of getting the data which i am successfully retrieving from the front end via this server page. Now I just need to refactor the logic in my react app to handle this data. – Jonny Aug 08 '19 at 15:35
0

Environment variables will help you in both cases. You can use dotenv library. The code examples are simplified to focus on your issue.

  1. Assuming your React app makes a request to a back-end endpoint (localhost:9000/endpoint) which will be requesting data from the third party service (in this case using got library), you will get the auth key from environment variable:
require('dotenv').config();  // init env vars
const got = require('got');
const express = require('express');

const router = express.Router();

// getting API key from env variable
const apiKey = process.env.AUTH_KEY;

// GET localhost:9000/endpoint
router.get('/endpoint', async (req, res) => {
  // requesting data from 3rd party service
  const response = await got('https://thirdpartyservice.com/api', {
    headers: {
      'x-auth-token': apiKey, // the auth token header
      json: true, // assuming response will be "application/json"
    },
  });

  // passing data to React
  res.json(JSON.parse(response));
});
  1. You should store the back-end service URL in an environment variable as well. You might have two .env files for development and production environments respectively:

Development:

# .env file on your localhost
AUTH_KEY = <your_secret_key>
API_URL=localhost:9000/

Production:

# env vars on heroku
AUTH_KEY = <your_secret_key>
API_URL=<api_server_name>.herokuapp.com/

And passing the URLs to your React app:

require('dotenv').config();  // init env vars
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

// your api server URL from env vars
const apiUrl = process.env.API_URL;

// pass the api URL to your React app
ReactDOM.render(
  <App apiUrl={ apiUrl } />,
  document.getElementById('root'),
);
  • Hi @Anton, thanks a lot for your answer here. Sandor's answer much more closely resembles my current build, and have tried it out and it works, so i will go with that but thank you for taking the time to answer. – Jonny Aug 08 '19 at 15:37