Home > Mobile >  Cannot retrieve data from API in production mode (Works in dev mode) using Express Reactjs
Cannot retrieve data from API in production mode (Works in dev mode) using Express Reactjs

Time:07-20

I'm a beginner trying to build a full-stack application using Express for the server-side and reactjs for the frontend. Basically, I want to call an API, retrieve the JSON-format data, and use that data on the frontend side.

What happens is that, when developing locally, I run the server and frontend code individually (using concurrently), and I can fetch data from the API without any issue. But, ultimately I want to deploy this full-stack application to Vercel.

So, I build the file with

npm run build

and then test the production environment locally using

serve -s build

When I open the production env. link, it doesn't seem to fetch data from the API. I can't figure out why this seems to happen.

Details below:

code directory

Code working directory

pacakge.json (main part for production)

{
   ...

  "main": "server.js",
  "scripts": {
    "start": "node server.js",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  },

  "proxy": "http://localhost:5000"

}

pacakge.json (main part for development)

    {
       ...
  "main": "server.js",
  "scripts": {
    "server": "node server.js",
    "frontend": "react-app-rewired start",
    "start": "concurrently --kill-others \"npm run frontend\" \"npm run server\"",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  },
  "proxy": "http://localhost:5000"

    }

server.js

/set is the relative endpoint that calls the actual API. I have changed the api address for security reasons, but as I said I confirmed that the API works properly on development environment.

const express = require('express');
const app = express();
const path = require('path');
var cors = require('cors')
const bodyParser = require('body-parser');
const fs = require('fs')
const https = require('https')
const axios = require('axios')

if (process.env.NODE_ENV !== 'production') {
    require('dotenv').config();
}
const port = process.env.PORT || 5000;
console.log("Inside server.js >>>")

app.use(bodyParser.json())
app.use(express.json())

app.use(cors({ origin: true, credentials: true }));

app.post('/set', (req, res) => {
    
  const httpsAgent = new https.Agent({
    ca: process.env.REACT_APP_CERT,
    cert: process.env.REACT_APP_CERT,
    key: process.env.REACT_APP_KEY,
});

    try {
        const instance = axios.create({
            httpsAgent
        });

        const options = {
            url: 'https://12.34.56.78/abcd',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Credentials': true,
                'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
                'Access-Control-Expose-Headers': '*',
            },
            data: { some: json data
            },
        };
        instance(options)
            .then(async (response) => {
                res.json(response.data)
            })
            .catch(err => res.send(err));
    } catch(err){
        console.error("GG", err);
    }
});   

if(process.env.NODE_ENV==='production'){
    app.get('/',(req,res)=>{
        app.use(express.static(path.resolve(__dirname,'build')))
        res.sendFile(path.resolve(__dirname,'build','index.html'));
    })
}

app.listen(port, () => console.log(`app listening on port ${port}!`));
module.exports = app

Function for API call inside reactjs

async function req(postdata) {

const instance = axios.create({
});

const options = {
    url: 'http://localhost:5000/set',
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Credentials':true,
      'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
    },
    data: postdata,
};
const data = instance(options)
    .then(async (response) => {
      return response.data
    })
    .catch((e) => {
      console.log('Network Error', e);
    });

return data;

}

Things I tried so far:

  • I checked the Network response in the developer tools of the browser. The screenshots of what it looks like when the API succeeded Vs when API failed to fetch data is posted below. At first glance, we can see that the response header is not shown when the API failed to fetch data.

Network response when API fails to fetch data

Network response when API fails to fetch data

Console log axios network error message

Console log axios network error message

Network response when API works in the development environment

Network response when API works

  • While testing the production mode with serve -s build, I also tried to run the server manually node server.js. In that case, the API was fetching data. Does this mean the express server is somehow not up and running in the production build? Although, the static index.html file is being served properly when I open the production link which should mean the server as such is running right..?

Hope the above references are good enough to help me out! How should I go about solving it? Please help me out as it's driving me mad!

CodePudding user response:

I managed to find a solution for this. So, to get the API call working in production,

following are the two changes I made.

  1. In server.js

Had to change the cors() part like this

app.use(cors({ origin: "*", credentials: true }));
  1. In the function for API call in reactjs

Had to remove the http://localhost:5000 and just make the request with relative endpoint /set in my case.

const options = {
url: '/set',
method: 'POST',
headers: {
  'Content-Type': 'application/json',
    'Access-Control-Allow-Origin': '*',
    'Access-Control-Allow-Credentials':true,
  'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE,PATCH,OPTIONS',
},
data: postdata,

};

Pushed the changes to vercel and verified that API is able to fetch data!

Still, even after making these changes, I cannot imitate the production environment with serve -s build (API call doesn't work)..

  • Related