How to deploy localhost APIs in production

Issue

This is the first time that I’ve ever deployed a web application to production. I’m using Heroku and have followed a tutorial via Udemy. I can provide the repo for the tutorial if necessary, but I think this is 100% on my end.

All of my API calls right now are to localhost:8000/api/v1/xxxxxxxx, and I see that in production—the calls aren’t pulling in data. The error message that I’m getting in the console is: net::ERR_CONNECTION_REFUSED. I noticed this when I shared the prod URL with my husband, and he wasn’t able to view any of the backend data on his laptop.

Everything works on my laptop using Safari, Chrome, Firefox, and Brave browsers—including in incognito mode—but it won’t work on any other machine—so I know that I did something wrong here. The site works for me using localhost and prod URLs.

I feel like a complete noob asking this question, but am I supposed to change the API URLs? I feel like that answer is yes, but where do I put the prod URL that I’m using with Heroku? I don’t have the Heroku URL anywhere in my code.

This is a MERN app, and I’m using a proxy if that’s helpful. It’s in my package.json file as "proxy": "http://localhost:8000".

Please feel free to check out the site itself—the URL is r2bdb.herokuapp.com. You can log in with [email protected] and the password is password. Everything there is dummy data if it does actually load for you.

This is the code from my server.js file.

import express from 'express';
const app = express();
import dotenv from 'dotenv';
dotenv.config();
import 'express-async-errors';
import morgan from 'morgan';
import cors from 'cors';
import nodemailer from 'nodemailer'

import { dirname } from 'path';
import { fileURLToPath } from 'url';
import path from 'path';

import helmet from 'helmet';
import xss from 'xss-clean';
import mongoSanitize from 'express-mongo-sanitize';

// db and authenticateUser (mongodb + prisma)
import connectDB from './lib/connect.js';
import prisma from './lib/prisma.js';

// routers
import authRouter from './routes/authRoutes.js';
import sandboxRouter from './routes/sandboxRoutes.js';
import volunteerRouter from './routes/volunteerRoutes.js';
import eventRouter from './routes/eventRoutes.js';
import politicalRouter from './routes/politicalSkillsRoutes.js'
import lifeRouter from './routes/lifeSkillRoutes.js'

// middleware
import notFoundMiddleware from './middleware/not-found.js';
import errorHandlerMiddleware from './middleware/error-handler.js';
import authenticateUser from './middleware/auth.js';

if (process.env.NODE_ENV !== 'production') {
  app.use(morgan('dev'));
}

const __dirname = dirname(fileURLToPath(import.meta.url));

// only when ready to deploy
app.use(express.static(path.resolve(__dirname, './client/build')));

app.use(express.json());
app.use(
  helmet({
    contentSecurityPolicy: false,
  })
);
app.use(xss());
app.use(mongoSanitize());
app.use(cors());

app.use('/api/v1/auth', authRouter);
app.use('/api/v1/sandbox', sandboxRouter);
app.use('/api/v1/volunteer', volunteerRouter);
app.use('/api/v1/event', eventRouter);
app.use('/api/v1/political', politicalRouter)
app.use('/api/v1/life', lifeRouter)

// only when ready to deploy
app.get('*', (req, res) => {
  res.sendFile(path.resolve(__dirname, './client/build', 'index.html'));
});

app.use(notFoundMiddleware);
app.use(errorHandlerMiddleware);

const port = process.env.PORT || 8000;

const start = async () => {
  try {
    await connectDB(process.env.MONGO_URL);
    app.listen(port, () => {
      console.log(`Server is listening on port ${port}...`);
    });
  } catch (error) {
    console.log(error);
  }
};

start();

As I mentioned earlier, I don’t have a production URL anywhere in my code. I feel like that’s the issue, but I’m not sure where the URL would go if I’m correct. Every API call is similar to: axios.get(‘http://localhost:8000/api/v1/xxxxxxxxxxx’). My .env file lists the PORT as 8000, so I don’t have an environmental variable anywhere that has a prod URL.

Apologies for a silly, basic question—I’ve never actually made it this far deploying a site to production on my own. Please let me know if I need to provide more information—I wasn’t sure what information was really needed here and didn’t want to overload so I just used my server.js file.

Solution

I just figured out my mistake—I left out the baseURL. If anyone else runs into this, I fixed it by writing this into my code:

  let baseURL = '';

  if (process.env.NODE_ENV === 'development') {
    baseURL = 'http://localhost:8000';
  } else {
    baseURL = 'https://r2bdb.herokuapp.com';
  }

and then using baseURL + ‘/api/v1/xxxxxxxx’ in my axios calls.

Answered By – techmeowt

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published