[Solved] Making conditional API calls from an express Server

Can anyone help. I have built a web-page in react using the api from newsapi.org.

My web-page conditionally calls the api depending on what is selected in the web page. The api calls have been structured (in a file called api.js in the client folder structure) as per the code below:

My question is, how do i get express to make these requests instead? I need to make this change because newsApi no longer allow requests direct from the client but they can from a backend server (apparently)

//===========================================
(response from another stack-overflow post: You can’t make requests from the browser anymore, you’ll have to use a backend. I had the same problem and the easiest way around it was implementing a Node (Express) server. Source: Error 426 from newsapi.org once I deployed my site on Netlify)
//===========================================

I have done very little on the backend so far so this is really confusing me.

I’ve been googling and following this: https://www.youtube.com/watch?v=kJA9rDX7azM which gives me the basic idea but i’m struggling with how to do this for my particular use case.

can I get express to refer (require?) to ‘api.js’ and call the relevant functions where required or do i have to somehow move the api calls to express (where the relevant dependencies wont be available i.e. the path, searchTerm, sources and api key)

// Contents of api.js
import axios from "axios";

const baseUrl = "https://newsapi.org/v2";

export const getNews = (path) => {
const link = `${baseUrl}/top-headlines?sources=${path}&apiKey=${process.env.react_app_api_key}`;
  return axios.get(link);
};

export const getSearchNews = (searchTerm, sources) => {
  let link = "";
  if (sources) {
    link = `${baseUrl}/everything?q=${searchTerm}&sources=${sources}&apiKey=${process.env.react_app_api_key}`;
  } else {
    link = `${baseUrl}/everything?q=${searchTerm}&apiKey=${process.env.react_app_api_key}`;
  }
  return axios.get(link);
};

Can anyone help. I have built a webpage in react using the api from newsapi.org. The webpage conditionally calls the api depending on what is selected in the web page. The api calls have been structured as follows:

const baseUrl = "https://newsapi.org/v2";

export const getNews = (path) => {

  const link = `${baseUrl}/top-headlines?sources=${path}&apiKey=${process.env.react_app_api_key}`;

  return axios.get(link);
};
and

export const getSearchNews = (searchTerm, sources) => {
  let link = "";
  if (sources) {
    link = `${baseUrl}/everything?q=${searchTerm}&sources=${sources}&apiKey=${process.env.react_app_api_key}`;
  } else {
    link = `${baseUrl}/everything?q=${searchTerm}&apiKey=${process.env.react_app_api_key}`;
  }
  return axios.get(link);
};

There are different ways you could implement it.

  • Use one api route that you call from the frontend and on the backend check if search is not empty call getSearchNews else call getNews.
  • Use different api routes to call from frontend - one for getNews and one for getSearchNews.

Here would be and example for the first way: https://repl.it/@jenovs/LawfulHarshRobots#index.js (sources and search are passed as query parameters, i.e. url?sources=blabla&search=ablabl)

1 Like

OK, that looks like it could work i’ll take a look, thanks :+1:

You can’t call the same api.js in your backend by require (and in your frontend by import at the same time). It is possible, but you’d have to setup babel/webpack that’s not very simple.
You’ll likely need to duplicate this api.js file for nodejs and use the require syntax instead of import syntax.
Even if you could do it, you’d have to create each route separately on the express server, something like yoursite.com/api/get-news and yoursite.com/api/get-search-news etc.

The most efficient way in my opinion would be to create a proxy route.
Instead of using https://newsapi.org/v2/some/path/to/resource from your frontend (api.js), you’d call your proxy URL https://yoursite.com/newsapi/v2/some/path/to/resource.

The /newsapi on your site route is the proxy route which simply forwards the request to the actual newsapi.org site and returns back the response.

You can create such a proxy easily by using this http-proxy-middleware package.

Sample code:

Your express server file:

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();

app.use('/newsapi', createProxyMiddleware({
  target: 'https://newsapi.org',
  changeOrigin: true,
  onProxyRes: function(proxyRes, req, res) {
    // Add the API key to the request.
    // So you don't have to expose the API key in the frontend requests
    // which is the one of the big reason for creating this proxy
     proxyRes.headers['X-Api-Key'] = process.env.react_app_api_key; // use the correct env variable
  }
}));

app.listen(3000);

This code has not been tested. It may or may not work. It is just to give you a general idea of how it will be set up.
Once this is set up, just call the requests from your frontend like this:

https://yoursite.com/newsapi/v2/top-headlines?sources=whatever

1 Like

So, to clarify, index.js and api.js on the backend (so i’d need to move my api key to a .env in the backend folder?)

So none of my original api.js code would now be on the frontend?

How would i then call this on the frontend?

Sorry to be slow but I’ve not done any fullstack stuff to understand how this would fit together?

Thanks, I’m OK with npm and package.json, it’s Express/Node and it’s integration with React (create-react-app) i’m confused about

Yes. You should create a proxy server that will handle all the calls to news api.
P.S. You won’t see .env file in the repl I posted, but it’s there :slight_smile:

Here’s a frontend example: https://codepen.io/jenovs/pen/BaKOeQr?editors=1010

Awesome, thank-you, i’ll take a look

Great, thanks, I haven’t looked at middleware at all so this could be an opportunity to understand what it is/give it a try :+1:

Hi Jenovs, Just to let you know I’ve finally managed to get this working by using the code you rewrote for express above (in the one api route example you gave above) and your example for how to use the result in the front end.
By taking both these pieces of information I was able to fix my app and deploy it with a backend express server (to make the api requests) to heroku. The API requests are returning results and my app is working again (https://github.com/char502/new-york-times)
I really appreciate your help as this was a key project on my portfolio to show employers so I needed it up and working again, thanks so much for your help! :grin:

1 Like