ReactJS backend requests and proxy - reactjs

I have a couple of questions regarding how ReactJS should work in development and production. My ReactJS application was built starting from creare-react-app boilerplate. I have a SpringBoot backend listening on port 8080. The first thing I noticed is that if I set a code like this to make requests the code hang:
async componentDidMount() {
...
const response = await fetch('http://localhost:8080/api/compliance');
I need to convert it into:
async componentDidMount() {
...
const response = await fetch('/api/compliance');
and then add the line:
"proxy": "http://localhost:8080",
and this works fine. The problem is that when I put this in a pre-production environment (or integration environment) where I have a URL like http://www.mywebsite.com I got:
Invalid Host Header
Looking on the web I noticed that probably this could be to:
1. proxy that checks. the HTTP Header host and verify it to avoid security attacks
2. webpack package
I would like to understand:
1. Is proxy really necessary to let ReactJS app talk with its backend?
2. If no, how I can solve the issue (currently solution on the web didn't solve my problem)?

Generally proxy is not meant for production. Your app should provide both app and api on same port, on one server. https://stackoverflow.com/a/46771744/8522881

Related

How to connect a React frontend on Netlify to a Flask backend on PythonAnywhere

TLDR: React app interfaces properly with Flask API on PythonAnywhere when hosted locally but not when a static build is hosted on Netlify. Perhaps the proxy information is missing from the build?
EDIT 1:
Here are the errors in the browser console:
I've created a Flask API that pulls machine learning models from Amazon S3 and returns predictions on data input from POST requests. I've put this API on PythonAnywhere.
I've also created a React frontend which allows me to input data, submit it, and then receive the prediction. When I host this app locally, it behaves appropriately (i.e. connecting to the Flask app on PythonAnywhere, loading the models properly, and returning the predictions).
I've tried deploying a static build of the React app on Netlify. It behaves as expected, except for anything that requires interacting with the Flask App. I have a button for testing that simply calls the Flask app in a GET request, and even this is throwing a 404 error.
I checked the error and server logs on PythonAnywhere and see nothing. The only thing I can thik of is that my proxy which lists the domain of the PythonAnywhere app in my package.json file is for some reason unincluded in the build, but I don't know why this would be the case.
Has anyone else run into a similar issue or know how I can check to see if the proxy information is included in the static build? Thanks in advance!
Thanks to #Glenn for the help.
Solution:
I realized (embarrassingly late) that the requests were not going to the right address, as can be seen in the browser console error above. I was using a proxy during development, so the netlify app was calling itself rather than the pythonanywhere API. I simply went into my react code and edited the paths to pythonanywhere. E.g.
onClick={ async () => {
const response = await fetch("/get", {...}}
became
onClick={ async () => {
const response = await fetch("https://username.pythonanywhere.com/get", {...}}
As #Glenn mentioned, there may have been a CORS issue as well, so in my flask application I utilized flask_cors. I can't say for sure that this was necessary given that I didn't test removing it after the fetch addresses had changed, but I suspect that it is necessary.
Hopefully this can help someone else

Change all api calls URL react when in production

I would like to know if it is possible to alter all the api calls made from my react app to my backend server. I used to have the static files to sit around in my project root directory, so when I made an api call with axios like await axios.get('/api/my-endpoint') it all worked fine and my requests were translated to GET https://www.example-url.com/api/my-endpoint. But now I am migrating to AWS EC2 and decided to serve static files from AWS S3. So now since the api is in a remote server all my api calls are broken. I need to replace all api calls to https://www.another-example-url.com/api/.... I know I can set the new URL in an environment variable, but that would force me to manually alter all of the api URLs in my front-end codebase. I would not be very happy to do this, since there are almost a thousand of them.
I tried to set the axios baseURL like so:
import axios from "axios";
const instance = axios.create({
baseURL: "www.another-example-url.com"
});
export default instance;
but then all the requests were translated to GET https://www.example-url.com/www.another-example-url.com/api/my-endpoint
Is there a lazy way of doing this? Or do I have to manually alter them all?
You can easily set this using "proxy" field in package.json file of client side. Just add following line
...
"proxy": "https://www.another-example-url.com",
...
edit: I almost forgot that you were asking for production build. So react-amazing-proxy is an alternate to create-react-app proxy which can have feature to use proxy in production build.
Another lazy way, if you are familiar with docker, would be to Dockerize your development built.

Can't solve strict-origin-when-cross-origin. React + AdonisJS

I have a server, in which I'm running two different applications. The frontend (express + React) is running on 443 port, and the AdonisJS api is running on 3333 port. They share the same domain (something.com, for example), but I need to add the port when calling the api. The problem is, when I try to hit an endpoint from my api from React, I get this error: strict-origin-when-cross-origin. Actually, I'm not sure if this is an error, but I can't make any request at all. From another client, such as Insomnia, the request works like magic.
I fixed the issue by changing the AdonisJS cors config file. I switched the origin value from true to *.
Besides adding the proxy instruction in package.json
"proxy": "http://localhost:5000", I also had to remove the host from the api url request, so:
const apiData = await axios.get('http://127.0.0.1:5000/api/get-user-data');
became
const apiData = await axios.get('/api/get-user-data');
The link provided by #ShawnYap was really helpful https://create-react-app.dev/docs/proxying-api-requests-in-development/

How to deploy chat server on heroku

So I've just created simple chat app with React, NodeJS, Express.JS and SocketIO. I'm going to deploy it on Heroku.
The problem is I'm not sure could I run both frontend and backend on the same URL. When I first created this chat locally, I've run front-end on localhost:3000 (default by Create-React-App) and backend on localhost:8000.
For the front-end side, I did it like this in external API.js file:
import io from 'socket.io-client';
let socket;
export const api = {
open: () => {
socket = io('http://localhost:8000');
}
}
For the backend side, I did it like this:
let express = require('express');
let io = require('socket.io')(8000);
So, you see, they're both on different ports. On my computer, it works perfectly. I'm not sure they could work locally on the same port (if I'm trying to switch 8000 port on back-end side to port 3000 it unfortunately doesn't work correctly - front and backend can't work on the same port, HTTP 404 error occurs).
My question is: is there any reason/is it even possible to put it on the same port? Because here's the problem number 2:
I've tried to deploy it on heroku, for the front-end side I've used Heroku Buildpack for create-react-app and it works fine, but totally don't know how to use it to deploy server-side. Should I create separate heroku address for the backend? And, at the code above, change paths like:
let socket;
export const api = {
open: () => {
socket = io('http://myherokuaddress');
}
}
and
let express = require('express');
let io = require('socket.io')(http://myherokuaddress);
?
In heroku you can't define port manually. use this code instead of port 8000.
process.env.PORT
You can do what Zenith said, however, the best practice is to use different servers for frontend and backend code, that way you can build mode frontend apps that uses the same backend code. And, if for some reason, your frontend server is down, you will only need to host the frontend code anywhere else and still using the same backend.

Redirect from http to https on localhost with create-react-app to test with Lighthouse

I have configured create-react-app to use https in my local development environment. I would now like to convert my React application to a progressive web app and I plan to use Lighthouse to check my status. I am running Lighthouse as a Chrome plugin, but I am having trouble with the part when it is checking if my HTTP requests are redirected to HTTPS. They are not.
I have been crawling through my node_modules and I have taken a look at webpack-dev-server that is bundled with create-react-app. I have tried to make some changes, but the best I have managed so far is that I have gotten "Too many redirects".
TL;DR: How can I configure create-react-app to redirect all requests from http to https on my local dev environment?
Here's the code from my create-react-app if you are having trouble with just the redirect part. I'm doing it manually since Heroku doesn't automatically handle it. But this actually needs to be handled on the server because it makes the app visibly load twice if it has to redirect to http. But for now, I'm redirecting in the constructor of my App component.
constructor(props, context) {
const url = window.location.origin
if (!url.includes('localhost') && !url.includes('https')) {
window.location = `https:${url.split(':'))[1]}`
}
}
For your purposes, you'd just need to take out the localhost part and make the new url a little differently (because of the port).
I'm using ramda here, but lodash also has a tail function you can use.
import { tail } from 'ramda
...
constructor(props, context) {
const url = window.location.origin
if (!url.includes('https')) {
window.location = `https:${tail(url.split(':')).join(':')}`
}
}
#Fmacs, for redirection of HTTP traffic to HTTPS, instead of using local dev-server, deploy your app on any environment like Heroku or Firebase. Firebase is very simple. I see that you also have other issues running the create-react-app that you created. I have explained how to do this in simple steps in a blog post with sample code in GitHub. Please refer to: http://softwaredevelopercentral.blogspot.com/2019/10/react-pwa-tutorial.html

Resources