Can't receive a response message when using proxy-middleware between react ui and express backend - express

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

Related

Flutter & GraphQL

Not sure why am I getting this error.
Please help.
const express = require('express');
const graphqlHTTP = require('express-graphql');
const app = express();
app.use('/graphql', graphqlHTTP({
graphiql: true
}));
app.listen(4000, () => {
console.log('Listening to port 4000');
});
From their doc
const { graphqlHTTP } = require('express-graphql');

How do I send response object from my get request to the front end with Express and Axios?

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

cors error preflight alow origin mismatch for apollo client and sever

Overview
I am trying to get authentications set up in Apollo but I keep running into this network error: CORS error PreflightAllowOriginMismatch. I have looked and tried so many solutions on the internet but nothing is working.
I have my client running on localhost:3000 and my server on localhost:4000.
Code
//client index.js
import React from 'react';
import { render } from 'react-dom';
import { ApolloProvider } from '#apollo/client';
import App from './App';
import { ApolloClient, createHttpLink, InMemoryCache } from '#apollo/client';
const httpLink = createHttpLink({
uri: 'http://localhost:4000/graphql',
credentials: 'include',
});
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
});
render((
<ApolloProvider client={client}>
<App />
</ApolloProvider>
), document.getElementById('root')
);
//server index.js
const { ApolloServer } = require('apollo-server-express');
const express = require('express');
const cors = require('cors');
const schema = require('./schema');
const models = require('./sequelize/models');
const server = new ApolloServer({
schema,
context: req => ({
...req,
models,
})
});
const app = express();
var corsOptions = {
origin: 'http://localhost:3000/',
credentials: true // <-- REQUIRED backend setting
};
app.use(cors(corsOptions));
server.applyMiddleware({ app, cors: false });
app.listen({ port: 4000 });
I'm honestly lost at this point. I new to apollo and for the life of me cannot find what i am missing.
Although I am unsure about the security the following changes fixed my issue.
remove
origin: 'http://localhost:3000/',
credentials: true // <-- REQUIRED backend setting
};
app.use(cors(corsOptions));
update
server.applyMiddleware({ app, cors: {credentials: true, origin: true} });
the final file:
//server index.js
const { ApolloServer } = require('apollo-server-express');
const express = require('express');
const schema = require('./schema');
const models = require('./sequelize/models');
const server = new ApolloServer({
schema,
context: req => ({
...req,
models,
})
});
const app = express();
server.applyMiddleware({
app,
cors: {credentials: true, origin: true}
});
app.listen({ port: 4000 });

How can I get data passed from axios post request through to nuxt serverMiddleware?

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.

Using createProxyMiddleware for the same routes on FE and BE while avoiding CORS

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!