Proxying api requests in production for React/Express app - reactjs

I'm working on a MERN-stack project using separated repositories (backend & frontend), In development environment, I was using "proxy" to connect the server API with react, and it was working perfectly.
//package.json in react
{
...
"proxy": "http://localhost:8000/",
...
}
But when I switched to production environment and replaced the proxy value with the deployed link, "proxy" is no longer supported. I did a search about it and I figured out that it's only for development env, and I tried several solutions found there on the internet but with no luck!
By the way, I'm deploying the backend with Heroku, and the frontend with Netlify. Right now, both of them are deployed without any error, but there is no connection between the backend and frontend.

In production we can't use (proxy).. instead we can set a variable in the frontend for the backend URL, and vise versa.
Let's start with backend configurations:
app.use(cors({
origin: "frontend_URL",
credentials: true
}));
Now, let's see the frontend config:
set a variable anywhere you prefer:
export const API_URL = "URL";
in the file where you call your API:
import axios from "axios";
import { API_URL } from "./your/path";
axios.defaults.withCredentials = true;
axios.get(`${API_URL}/your/route`);
and now you are ready to deploy...

Related

locally host firebase backend with react frontend together, for debugging

I am building a react website with firebase functions backend.
I'm using firebase serve to locally host the node.js backend that I connect to my react code through express API endpoints, and I am using react-scripts start to test my react frontend app.
all my get requests in my react app use /some endpoint to communicate with my firebase localserver. But they are running on different ports. firebase serves it on localhost:5000 while react live server hosts it at localhost:3000.
I tried many things and couldn't get any useful way to make this work. I at last added my react project as a subfolder in my firebase project and made the hosting public path at firebase.json to my react build directory. It works now but I always have to run npm run build on my react app on every change, to make it compile my app into the build directory, which is painfully slow.
What is the proper way to do this? debug react app and firebase backend together.
I finally enabled cross-origin-requests on my server using cors module
Serverside code
const cors = require("cors");
app.get("/test", (req, res) => {
return cors()(req, res, async () => {
res.send("working...");
});
});
Serverside code
And then adding a simple config file in the react side, to switch between debugging and deployed testing really helped.
config.js
var domain = "";
// domain = "http://localhost:5000";
export {domain}
then whenever I use apis in react, I simply comment/uncomment the second line to switch between local and deployed testing.
Then whenever I use APIs, I append `domain` before every url in all references, eg fetch requests
import { domain } from "config.js";
fetch(domain + "/int-search", ...
Then it worked fine running both the firebase backend and the react application on localhost, using firebase serve and npm start for my react app.

Heroku: Django backend is not working, getting error GET http://localhost:8000/api/todos/ net::ERR_CONNECTION_REFUSED

I actually created a fullstack todo app with django as backend and react as frontend. The frontend is working perfectly fine, you can that here -> https://ym-todo-application.herokuapp.com. But somehow my application cannot connect to the django backend, also on inspecting on browser i saw this error -> GET http://localhost:8000/api/todos/ net::ERR_CONNECTION_REFUSED.
Containing lot of files and code so i pushed them on bitbucket to make it easier to debug. here's the link https://bitbucket.org/Yash-Marmat/todo-app-fullstack/src/master/.
Thanks in advance.
You need to change the REST API server address. The localhost:8000 is the server address used in the development.
What is more, I see in your code that each time you write the request you have hard-coded server URL. You don't need to do this. You can set the server address by setting baseURL:
import axios from "axios";
if (window.location.origin === "http://localhost:3000") {
axios.defaults.baseURL = "http://127.0.0.1:8000"; // development address
} else {
axios.defaults.baseURL = window.location.origin; // production address
}
Then in the request, you only write the endpoint address, example:
axios.put(`/api/todos/${item.id}/`, item)
Please see my article Docker-Compose for Django and React with Nginx reverse-proxy and Let's Encrypt certificate for more details about Django and React deployment.

How to add react.js to spring mvc application

I have a Spring MVC application (jsp as a views) and i want to add react.js as a frontend. I have a couple of questions:
1. Where i should place my create-react-app folder or it doesn't matter.
2. Is there a way to run the application from maven (war) only. I mean that i know only one way to run application it is start backend from maven and start react.js from npm start. But this approach requires to use proxy or cors (or i'm wrong). I am using IntellijI IDEA and WebStorm.
project structure here
It doesn't matter
You are right that you should run it on different servers for spring and react.
You can proxy your api request to the backend to avoid CORS issue.
Copy this to your src/setupProxy.js in your create-react-app. More info here
const proxy = require("http-proxy-middleware");
module.exports = app => {
app.use(
proxy("/api", {
target: "http://jsonplaceholder.typicode.com",
pathRewrite: { "^/api": "" },
changeOrigin: true
})
);
};
Then you can proxy request to your backend using /api prefix. Example i can do something like fetch('/api/users') in my frontend react app

ReactJS/Next.js: CRA Proxy Does Not Work With Next.js (Attempting To Route API Request To Express server)

I'm currently upgrading a vanilla React app to use Next.js (version 7.0.0). The app was originally built with Create-React-App and utilizes the proxy built in to CRA's server.
In development my React app runs on port 3000 and I have an Express server running on port 5000. Prior to adding Next.js I'd been using a proxy object within the package.json file to route API requests to the server.
API request:
const res = await axios.get('/api/request')
Proxy object in package.json:
"proxy": {
"/api/*": {
"target": "http://localhost:5000"
}
}
This had been working great, but with Next.js I'm now getting an error:
GET http://localhost:3000/api/request 404 (Not Found)
^ This is supposed to be pointing to locahost:5000 (my server)
Does anyone know how I might be able to route API requests from a React/Next.js client to an Express server running on a different port?
OK, so I've figured this out. You can create a Node.js proxy for Express by using http-proxy-middleware
You can then configure the target option to proxy requests to the correct domain:
const proxy = require('http-proxy-middleware')
app.use('/api', proxy({ target: 'http://localhost:5000', changeOrigin: true }));

After deploying React/Express app to Heroku unable to start passport.js flow (page reloads instead) [duplicate]

I'm building a node + express server, with create-react-app to the frontend.
I used passportjs for auth routes handling, and all the stuff totally working on localhost ( backend on port 5000 and frontend on port 3000, with a proxy ).
When I deploy to Heroku, seems like the server can't recognize my auth routes and so heroku serve up static index.html.
If I test my APIs with Postman all seems to work ( I can see the html page for google oauth ), but with an anchor tag in my react app or manually writing the endpoint in the url, I can see only the same page reloading.
My server index.js:
const express = require('express')
const passport = require('passport')
const mongoose = require('mongoose')
const path = require('path')
// KEYS
const keys = require('./config/keys')
// MONGOOSE MODELS
require('./models/User')
mongoose.connect(keys.mongoURI)
// PASSPORT SETUP
require('./config/passport')
// CREATE THE SERVER
const app = express()
// EXTERNAL MIDDLEWARES
require('./middlewares/external')(app)
// ROUTE HANDLERS
require('./routes/authRoutes')(app)
// PRODUCTION SETUP
if (process.env.NODE_ENV === 'production') {
// express serve up production assets ( main.js, main.css )
app.use(express.static('client/build'))
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'))
})
}
// START THE SERVER
const PORT = process.env.PORT || 5000
app.listen(PORT)
Flow:
LOCALHOST:
react app starts -> I click 'Google Login' -> GET request to "/auth/google" -> google oauth flow -> redirect to "/" and my react app reappears, the user is logged in.
HEROKU:
react app on my-app.herokuapp.com/ -> click on "Google Login" -> the page reloads, nothing happens. the user is not logged in.
Please guys, help me.
Thanks
This is a result of the service worker being installed by default to make your app a Progressive Web App
To determine if this is an issue for you, test your heroku production mode app in incognito mode. The request for /auth/google should now reach the server and behave as it does in development.
Once you determine it is an issue, you can remove the
import registerServiceWorker from "./registerServiceWorker";
from your /client/src/index.js file.
You browser cache may already contain an installed service worker so you may have to
clear browser cache on a user browsers
uninstall the server worker programmatically
import { unregister } from './registerServiceWorker';
....
unregister();
I had the same issues with same symptoms exactly.
For me the cause was a typo in the keys: in server/config/prod.js I had a line reading cookieKey: process.env.COOKIE_KEY but in Heroku Config Variables that variable was named cookieKey. Renaming it to COOKIE_KEY inside Heroku solved the issue.
If you've followed the Stephen Grider tutorial one thing I'm wondering: Is your passport.js file in config or services? I see you've written in index.js: require('./config/passport')
whereas mine in index.js is require('./services/passport')
may not be your solution to the google oauth flow hanging in production but may help.

Resources