fetch request at express root router from react not working - javascript

I am trying to call the express root router ('/') from fetch api in react in production mode but it doesn't work.
I am using common server as I am using the react views as static files and renderning like this:
if(process.env.NODE_ENV == 'production'){
app.use(express.static(`${__dirname}/client/build`));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname+'/client/build/index.html'));
});
}
Also, i have already tried using the production hostname as the route in fetch but that doesn't work for me as I am using a proxy.
The complete story is that I am trying to get some tokens that I get from openshift oauth-proxy authentication. There are two containers, one for proxy and another for my web app. When the user is authenticated, proxy sends a token to 'localhost:8080' (which is my web app).
I am handling it this way,
app.get('/', function (req, res) {
if (req.headers !== undefined && req.headers['x-forwarded-access-token'] !== undefined && req.headers['x-forwarded-user'] != undefined) {
userDetails.accessToken = req.headers['x-forwarded-access-token'];
userDetails.username = req.headers['x-forwarded-user'];
req.session.token = userDetails.accessToken;
req.session.username = userDetails.username;
res.send({ accessToken: userDetails.accessToken, username: userDetails.username});
}
});
But when I call the above router from fetch api from react, i don't get the response. The app crashes.
When I am running it on development environment, I am running both on different servers, and when i write it completely, like 'fetch('http://localhost:3001')'
then it works.
I want it to work in production as well. Any help?
More details
The overall flow is, that I have deployed my react app on openshift. I am using oauth-proxy to authenticate the user and then land onto my react app once proxy sends me the authentication token in the react app.
There are two containers, proxy and web-app, inside the proxy-app pod. When i go to the route of the pod, it takes me to the keycloak login page where i enter my credentials, once authenticated, proxy send the auth-token in the headers to it's sidecar container which is my web-app (running on localhost:8080 inside the pod.) Proxy sends the headers to the localhost:8080/ (webapp) which is the root of the web app. Now here, i have to make a fetch request from client to this route and get the token(which i am not able to since it doesn't work this way probably because i am using a proxy which is running on different host than my web app). But when i make request on other routes like ('/api/xyz'), it works like charm. There is something with the root route and proxy that is creating the issue.

It worked when I added cors in my react code. I had it in my server code but not on react.
fetch('/auth', {
credentials: 'include',
mode: 'cors'
})

Related

Getting error on my express project: TypeError: Cannot read properties of undefined (reading 'prototype')

For some reason I'm getting the TypeError: Cannot read properties of undefined (reading 'prototype') on my javascript file. From what I see online, people seem to find that importing {response} from express was the culprit, but I'm not doing any of that.
import { Button } from '../Button';
import "./index.css";
import {clientId,clientSecret} from "./config.json"
import passport from "passport";
const express = require('express');
const app = express();
var DiscordStrategy = require('passport-discord').Strategy;
export const OAuth = (): JSX.Element => {
var scopes = ['identify', 'guilds', 'guilds.members.read'];
passport.use(new DiscordStrategy({
clientID: clientId,
clientSecret: clientSecret,
callbackURL: 'http://localhost:3000',
scope: scopes
}))
app.get('/auth/discord', passport.authenticate('discord'));
app.get('/auth/discord/callback', passport.authenticate('discord', {
failureRedirect: '/'
}), function(req:any, res:any) {
console.log(res)
res.redirect('http://localhost:3000') // Successful auth
});
async function openLink(url:any) {
window.open(url)
}
return (
<div>
<Button onClick={async() => await openLink("link goes here")} className="discordconnect">
Connect Discord
</Button>
</div>
);
}
export default OAuth;
TypeError: Cannot read properties of undefined (reading 'prototype')
This error seems to happen when you are trying to run express in a browser environment.
(See code sandbox with the same error)
Express is a web server. It runs on node.js and is typically started from your terminal prompt on your computer. It provides responses to http requests sent from a browser.
React is a front end UI framework that run inside your browser. It manipulates the HTML content displayed on the page according to loaded data and user interaction with that page.
It looks like you are trying to start an express app from a React component running in your browser. This is not supported by Express. Express cannot be run in the browser. In fact, no server can be hosted from a web browser due to browser security policies.
I don't know what it is you are trying to do, but you need to fundamentally rethink your approach here.
Typically when you begin developing this, you would create a server with express that serves a react application. You start the server from your computer's command line terminal, and then navigate to a URL served by that server which loads your react app in your browser.
You never create a server from a React component because that just isn't possible, nor does it make very much sense.

Redirecting backend calls in Vue application

I am trying to deploy my website written in Vue to a static webhosting service (AWS S3).
I have been using the bencodezen boilerplate which seems to be generated using Vue-CLI. The boilerplate comes with a pre-configured development server such that you can redirect the backend calls (using axios) to either a mock backend or to a production backend:
vue.config.js
module.exports = {
[...]
// Configure Webpack's dev server.
// https://cli.vuejs.org/guide/cli-service.html
devServer: {
...(process.env.API_BASE_URL
? // Proxy API endpoints to the production base URL.
{ proxy: { '/api': { target: process.env.API_BASE_URL } } }
: // Proxy API endpoints a local mock API.
{ before: require('./tests/mock-api') }),
},
}
All calls to myurl.com/api/* will be directed to either the mocked backend or the API_BASE_URL if such is defined. This works fine while using the vue-cli-service serve development server but I'm failing to understand how to translate this to AWS S3, or any other webserver suited for production. If I try to make a login, post-request I get the following response from AWS:
405 Method Not Allowed
Indicating that the call was never redirected (AWS S3 doesn't allow POST calls).
Is it possible to redirect the API-calls directly from the web browser to the backend without going through the webserver? If not, how to I setup my production webserver in such a ways that the calls to myurl.com/api/* are automatically forwarded?
In the production environment (where devServer config does not apply) you need to manually handle the URLs, using some logic to figure out where the requests need to go. If the backend is not on the same host as the frontend, something like this:
const apiPath = process.env.NODE_ENV === 'development' ? '/api' : 'https://mybackendurl.com/api';
axios({
url: `${apiPath}/login`,
method: 'post',
headers: myHeaders,
// etc
})
You probably won't want to do that before every API call so I recommend making some sort of API service you can import and plug into axios. Then you can do something simple like url: API.Login()

Not allowed to request resource (fetch error)

I'm trying to hosting my Express server on my personal computer because it needs Linux + Wine (for building commands). And for using him, I've opened my ports, and I can access to my Express page normally, but if I try to fetch the URL from the Express app, it won't work.
Here's the errors : https://imgur.com/4hdznw7
Here's the code of my Express app : https://hastebin.com/mihizegatu.typescript
Warning I've tried to publish my Express app on Heroku, and I can fetch it. But if I fetch my Express app from my personal computer, it won't works (errors upper).
Do you have an idea of why it doesn't work ?
Thanks in advance,
Corentin de Maupeou

proxy not working for create-react-app in production

I am working with reactjs(create-react-app) to create a dashboard application, In my application i am calling multiple host (for that I have configured multiple proxies in package.json to avoid CORS).
ex- www.app.demo1.com, www.app.demo2.com, www.app.demo3.com...
"proxy": {
"/demo1/api/":{
"target":"www.app.demo1.com"
},
"/demo2/api/":{
"target":"www.app.demo2.com"
},
"/demo3/api/":{
"target":"www.app.demo3.com"
}
}
in application i am calling like-
try{
const host1 = process.env.NODE_ENV === 'production'?
'www.app.demo1.com/demo1/api': '/demo1/api/';
const host2 = process.env.NODE_ENV === 'production'?
'www.app.demo2.com/demo2/api': '/demo2/api/';
const host3 = process.env.NODE_ENV === 'production'?
'www.app.demo3.com/demo3/api': '/demo3/api/';
const resp1 = axios.get(host1)
const resp2 = axios.get(host2)
const resp3 = axios.get(host3)
}catch(){}
in development: when making request to /demo1/api/ it is being proxied to
www.app.demo1.com/demo1/api and i am getting the response. but
in production: I have deployed the application on github pages, although I am getting the below error,
enter image description here
Can anybody help..
Proxies are for development purposes only, and they are handled by webpack-dev-server. On production you need to make the calls to the actual host.
This is created because usually, on development, react is served by a standalone server meant just for that (hence, webpack-dev-server). On production, usually there is a backend (node? ruby? php?) that serves the pages and every call made is going to be to some endpoint with the same hostname.
Example:
In your development environment you have a node server running on port 3001 and your react code running on port 3000. When react fetches /api/user, you actually want http://localhost:3001/api/user, which points to your node server.
In your production environment, you have a server (nginx, maybe?) that forwards all /api calls to your node process, and for everything else it serves your react main index.html file (so you can use react-router, for example). In this case, whenever you request /api/user, this is going to be handled by your web server and routed properly.

Firebase Authentiction using Javascript

We are building a web app using firebase. We are using firebase hosting to host static files like CSS, images, and javascript. We are also using firebase functions to make web app dynamic.
const app = express();
...
app.use(express.static(__dirname + '/public'));
app.get('/', (req,res) => {
res.render('index');
});
I have a signIn.js in public folder and hosted on Firebase Hosting. When I try to access "firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier) {}" function in signin.js, I get an error that "Firebase" is not found.
I want to send OTP on user phone using Firebase. Now I am confused whether we should handle it on the client side in hosted JS files or we have to handle it at server side in server.js.
Also, how could I invoke a function in server.js files hosted on firebase functions from static js file hosted on firebase hosting?
firebase.auth().signInWithPhoneNumber is client side only. You also need to render an invisible reCAPTCHA with it too which can only be done client side. If you are using the Firebase Admin SDK, it allows you to create a user or update an existing user with a phone number but it assumes you verified the number via your own means.
If you need to provide authenticated access to some http endpoints via Firebase Functions, you can send the Firebase ID token of the phone authenticated user to that endpoint (you can get it on the client via currentUser.getIdToken()) and verify it via the Admin SDK verifyIdToken(idToken).

Categories