Hi I'm working on a isomorphic react app that uses passport.js for auth.
My problem is requests can come from the client, or from the server. If the request comes from the client, it's authenticated and all is good. BUT, if the request comes from the server, then the auth fails :(
Server (lots removed for sake of clarity):
server.use('/api/data', require('./api/data'));
server.get('*', async (req, res, next) => {
await Router.dispatch({ path: req.path, query: req.query, context }, (state, component) => {
<div>
{component}
</div>
);
data.css = css.join('');
});
});
/api/data:
router.get('/', auth.isAuthenticated, async (req, res, next) => {
res.status(200).send({result: 'working!'});
});
Routes:
on('/route', async (state, next) => {
// RESP IS A REJECTED RESPONSE :(
const resp = await fetch('/api/data');
const data = await resp.json();
return <Component data={data} />;
});
Related
I see that the request sent from the ui created using React is forwarded to the backend, but I can't get the response from the ui. There may be details that I missed as I am very new to these issues, thanks in advance :)
//react Login.js
function Login() {
const fetch = actions.fetchUser();
async function handleSubmit() {
try {
fetch();
} catch (err) {
console.error('err', err);
}
}
export default Login;
//index.js
import axios from 'axios';
export const fetchUser = () => async () => {
await axios.get('/api/login');
};
//setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
['/api'],
createProxyMiddleware({
target: 'http://localhost:5000',
}),
);
};
//express app.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
const port = 5000;
app.use(cors());
app.use(bodyParser.json());
require('./routes/login')(app);
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
// espress login.js
module.exports = app => {
app.get('/api/login', (req, res) => {
console.error('express login');
res.send('login');
});
First of all, do not mix cjs and mjs import/exports.
second of all, you export your middleware but never register/use it. At least your code does not show that part.
Here is very minimal example how you can proxy your react UI via express.
const express = require('express');
const proxy = require('express-http-proxy');
const app = express();
app.get('/api', (req, res) => {
res.send({my: 'data'});
});
// register other routes here
app.use(proxy('http://127.0.0.1:3000'));
app.listen(5000, '0.0.0.0', () => {
console.log('Server is running at http://127.0.0.1:5000');
});
React app content will be available on http://127.0.0.1:5000 with your routes.
And http://127.0.0.1:5000/api will be your express route.
Note: I assume your react app runs on the port 3000
I am trying to pull data from MongoDB to populate some timers in this app I'm building. However, I can't seem to send my response to the front end with Axios. Here is my route on the backend:
const express = require('express');
const router = express.Router();
const TimerModel = require('../models/Timer');
router.get('/', async (req, res) => {
try {
const timers = await TimerModel.find({});
console.log('Succesful get req', timers);
res.send(timers);
} catch (err) {
console.log(err.message);
res.status(500).send('Server Error');
}
});
module.exports = router;
My console.log in the try statement prints the correct data but I'm having issues with sending it to the front end. Here is the component:
import React, { useState, useEffect } from 'react';
import Timer from '../Timer/Timer';
import axios from 'axios';
import './Wrapper.css';
function Wrapper() {
//State effects
useEffect(() => {
axios
.get('/')
.then((res) => {
console.log(res);
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
});
const handleChange = (event) => {
setTitle(event.target.value);
};
const addTimer = () => {
const timer = <Timer title={title} key={timers.length} />;
let allTimers = timers.slice();
allTimers.push(timer);
setTimers(allTimers);
setTitle('');
};
return (
//JSX Code
);
}
export default Wrapper;
In the axios call I make, I get this weird object when I run console.log(res) and I get my index.html for the res.data. Why don't I have access to the timers object I made with my backend request? Isn't it being sent when I run the command res.send(timers) in my route?
You need to add your API url in axios request. Currently, axios is taking url of your React website that is why your response have index.html file of React website.
useEffect(() => {
axios
.get('api_url/')
.then((res) => {
console.log(res);
console.log(res.data);
})
.catch((err) => {
console.log(err);
});
});
You can save the result in a state like
`````````````
`````````````
const [time, setTimer] = useState(null)
useEffect(() => {
axios.get('/').then(res => setTimer(res.data)
}, [])
`````````````
`````````````
and then use time vairable where you want
const middleware = (req , res, next) => {console.log('Hello From Middleware');}
middleware();
app.get('/',(req, res) => {
res.send('hello world from the server');
})
I am trying to pass some data to my serverMiddleware using axios but I can't seem to be able to get the data in my serverMiddleware
guilds page script:
<script>
export default {
async fetch() {
const token = 'testToken'
const guilds = await this.$axios.$post('/api/guilds', { token })
}
}
</script>
serverMiddleware:
import axios from 'axios'
import express from 'express'
const router = express.Router()
const app = express()
router.use((req, res, next) => {
Object.setPrototypeOf(req, app.request)
Object.setPrototypeOf(res, app.response)
req.res = res
res.req = req
next()
})
router.post('/', (req, res) => {
console.log(req)
})
export default {
path: '/api/guilds',
handler: router
}
Token should be an object of key-value.
async fetch() {
const token = 'testToken'
const guilds = await this.$axios.$post('/api/guilds', { token: token })
}
Then you can take it from req.body in serverMiddleware.
I'm building an app using node.js on the server side and used create-react-app for the client.
When running locally I want to use render Home component for path '/home' like so:
<BrowserRouter>
<div>
<Route exact path="/home" component={Home} />
</div>
</BrowserRouter>
and on the server side I want to to use '/home' to get requests like so:
app.use('/home', require('./routes/home'))
where 'routes/home/' is an express router:
module.exports = router.get('/', (req, res) => {
res.send({ status: 200, data: 'Hello World!' })
})
The problem is that I got CORS error at first, so I added createProxyMiddleware in order to proxy the server responses:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
const portPrefix = 'localhost:3000'
const options = {
target: 'http://localhost:5000',
router: {
'dev.localhost:3000': 'http://localhost:5000'
}
}
app.use([`/home`], createProxyMiddleware(options));
};
But now, when I make a request from the client (port 3000) to '/home' the request is redirected to port 5000 and I get the res.send({...}) immediately (instead of rendering the Home component that is using axios to make the request and handle the response..)
My Home component:
import React, { useState, useEffect } from 'react'
import axios from 'axios'
axios.defaults.baseURL = 'http://localhost:5000'
const Home = () => {
const [loading, setLoading] = useState(true)
const [data, setData] = useState("")
useEffect(() => {
async function makeRequest() {
const res = await axios.get('/home')
setData(res.status === 200 ? res.data.data : "test string")
setLoading(false)
}
makeRequest()
}, [])
return (
<div className="container">
{ !loading && <h1>{data}</h1> }
Home Page
</div>
)
}
export default Home
I saw that there's a solution to avoid createProxyMiddleware and just add headers to the response:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:3000"); // update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
My question are:
How will adding headers behave on production?
Is the headers solution the better solution for local development, since createProxyMiddleware is there to assist with that I guess.
If I decide to use createProxyMiddleware, how can I use the same routes for both client and server (e.g. '/home' to render Home component on FE and '/home' for get requests on BE)? because now it "skips" the client side and goes straight to the server.
Thanks a lot!