CORS proxy error in react app and express server - javascript

I am running a React app with an Express server back-end on port:5000. I am making a request to one of my endpoint using the state of the element to get some data and then render it to the page. I initially setup the proxy in the package.json file of the React app as "proxy": "http://localhost:5000" (documentation. Now it was giving me a proxy error saying cannot proxy to localhost:5000. So I used CORS in my express server as a universal middleware for all of the routes using app.use(cors()).That removed the proxy error but the request is still not working (the code is not even reaching the endpoint because nothing is being logged to the console) and I am pretty sure it's because of the same error. Here are the code snippets
router.get("/", async (req, res) => {
var elements = [];
elements = await Element.find();
res.json(elements);
});
const getElements = async () => {
try {
console.log('getElements call')
const data = await axios.get("/api/elements");
console.log(data);
dispatch({ type: GET_ELEMENTS, payload: data });
} catch (e) {
console.error(e);
}
};
const { getElements, elements, loading } = elementContext;
useEffect(() => {
getElements();
}, [])
Expected behaviour: I want the endpoint to send an array name elements to the call which can then be set to the elements state using the reducer and then can be accessed by destructing in the end. I hope I have given adequate information. Any help will be appreciated. Thank you.

Related

How do I make my react app fetch my proxy API?

my api call isn't sending to the proxy url domain. I know that it isn't calling as the console.log in the server isn't going off. Could someone please help me?
//client package.json
"proxy":"http://localhost:3001"
//client app
useEffect(() => {
const apicall = async () => {
try{
const response = await fetch("/")
if (response.status !== 200){
throw new Error()
}
else{
console.log("api call was success")
console.log(response)
}
} catch(error){
console.log(error)
}}
apicall()
}, [])
//server
app.get("*", (req,res)=>{
console.log("apicalled")
res.cookie("refreshToken", 987654321, {
maxAge: 60000,
httpOnly: true
})
res.send("has cookie sent?")
})
Don't have an answer for you, but it looks like you're using create-react-app? I think if you've setup your own server, you don't need to set the proxy in your package.json.
I am running a small react app and trying to access an external api behind my company's proxies. I continue to get the cors error - I've tried setting a proxy in package.json and using setupProxy.js (separately), but haven't had any luck.

How can you test values passed to EJS file rendered by Express?

I am trying to test my express web application using mocha and chai, but I am unable to figure out how to test the HTTP requests being handled by express. I am using ejs as my view engine so most of my route handlers look like this:
const someRouteHandlerForGETRequest = async (request, response) => {
// usually some DB queries to get data to display in view
const someQuery = await pool.query('SELECT * FROM table');
var sampleData = someQuery.rows;
response.render('ejspage', {
user: request.session.username,
sampleData: sampleData
});
}
Because of this, I believe that my response.body is just an html file / html string (using postman I was trying to see what was in the response, it appeared to just be the html for the view)
How do I test the data being passed to the ejs file (in this example; sampleData) that is being returned from the node-pg database query?
My current attempt at testing is this:
const { assert } = require('chai');
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../index');
chai.should();
chai.use(chaiHttp);
describe('/GET activeorders', () => {
it('it should GET active orders', (done) => {
chai.request('http://localhost:3000')
.get('/activeorders')
.end((err, res) => {
res.should.have.status(200);
done();
});
})
})
Basically the only this I can test is the response status, beyond that I can't figure out to test any of the values that are being returned from database queries.
I have also tried separating the model from the controller by removing the queries to the database from the route handler and instead having the route handler call a function that returns the results. This doesn't solve my problem though because using chai-http to test a HTTP request still doesn't give me access to the data since the route handler is simply rendering the ejs page with the data.

GET Request repeatedly failed on the front end but not on backend

I'm working on a personal project that will allow users to find new books based on their preferences for the genre. The database I'm using is MongoDB. However, while I'm able to get all the data on the backend using Postman, I can't get it properly displayed on the frontend. At the moment, I'm just trying to get the data sent to the front end and at least console.log'd but it isn't making it that far.
Here is the code in the routes file.
router.get('/books/:genre', bookBuilder.get_some_books)
Here's the code on the backend that the routes file is pointing to and is working:
exports.get_some_books = async function (req, res) {
let { genre } = req.params;
try {
let books = await Book.find({"genre": genre});
if (books) {
res.json(books)
} else {
res.status(404).send({error: 'Not Found'});
}
} catch (err) {
res.status(500).send({error: err.message});
}
}
Here's my code on the frontend that is not working.
async getEverything() {
try {
let pbBooks = await axios.get(`/books/`, {
method: 'GET',
headers: {'Content-Type': 'application/json'},
params: {
genre: 'PB'
}
})
if (pbBooks) {
console.log(pbBooks)
} else {
this.$router.push('/Error');
}
} catch (err) {
console.log(`Network error: ${err.message}`)
}
}
My code stack is Vue.js, Express.js, Node.js and Axios. On the frontend, I've tried making the inner code of axios.get() into '/books/PB' and then tried getEverything(genre) along with /books/${genre} but neither seems to be working.
The error I am getting is a 404 Request Failed error that is from the catch block in the getEverything() function. I'm not sure why the frontend is unable to get the data when the backend works just fine. Is there anything I'm doing wrong?
404 is the HTTP status code for Not found, which implies there is no route setup on localhost for /books. Actually, /books would route to your app, not the backend (unless you have a proxy setup on your app server that redirects to the backend).
If a proxy were involved, it's likely misconfigured. Otherwise, the target URL in the Axios request should be <backend_url>/books (e.g., http://localhost:9999/books with the back running locally on port 9999, and the app on some other port).
Change
let pbBooks = await axios.get(`/books/`, {
...
to
let genre = "PB"
let pbBooks = await axios.get(`/books/${genre}`, {
method: 'GET',
headers: {'Content-Type': 'application/json'}
})
reason is the params part of the config object is converted to query strings (/books?genre=PB) instead of /books/PB, which is what the backend is expecting
More: https://masteringjs.io/tutorials/axios/get-query-params

Axios/Backend in React stops working after a while with no error

My React App takes user input from frontend and send it to backend via Axios where the info will be used to search through MongoDB. My App works fine for a few input, like around 5-6, then it will stop working with no error and I have no idea what is wrong and how to fix it.
Here is an example of my problem, this useEffect will happen when page load and take param from the url and send it to backend (the param change depends on what link the user clicks on). It will then send the information to backend via axios and the Info is used to search through MongoDB and will dynamically generate the page's text. After the user clicks on around 5 different links tho, this will stop working and the page generated will be stuck on the last page it was generated dynamically although the params in the url still change. I added console.log to see if useEffect was activating or not, and everytime I click on a Link, the console.log will work when the page load. Any lead will help, thanks!
frontend runs on port 3000 and backend runs on 3001
useEffect(() => {
const idInfo = {id};
axios.post('http://localhost:3001/info', idInfo);
console.log("testing")
}, [])
useEffect(() => {
fetch("/info").then(res => {
if(res.ok) {
return res.json();
}
}).then(jsonRes => setGetId(jsonRes))}, [])
This is the backend
router.route("/info").post((req, res) => {
console.log(req.body)
const idInfo = req.body.id;
console.log(idInfo);
current_id = idInfo;
})
router.route("/info").get((req,res) => {
Disease.find({_id: current_id})
.then(foundId => res.json(foundId))
})
This way, when you fetch('/api/info') in development, the development server will recognize that it’s not a static asset, and will proxy your request to http://localhost:3001/api/info as a fallback. The development server will only attempt to send requests without text/html in its Accept header to the proxy.
Conveniently, this avoids CORS issues and error messages like this in development:
Fetch API cannot load http://localhost:3001/api/info. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
https://create-react-app.dev/docs/proxying-api-requests-in-development/
src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:3001',
changeOrigin: true,
})
);
};
useEffect(() => {
const idInfo = {id};
axios.post('/api/info', idInfo);
console.log("testing")
}, [])
useEffect(() => {
fetch("/api/info").then(res => {
if(res.ok) {
return res.json();
}
}).then(jsonRes => setGetId(jsonRes))}, [])

How to pass Request cookies through node-fetch in isomorphic app?

I'm trying to build isomorphic project using React, Express and isomorphic fetch (based on whatwg-fetch on client and node-fetch on server), from this common boilerplate. I'm using cookies for my access token, and credentials: 'same-origin' on front-end side to send it to GraphQL -- works pretty well.
The problem is that I can't use the same solution for server side -- node-fetch just don't support using of XMLHttpRequest cookies from the box. My fetch request is under few abstract layers from router, so I can't just use cookie value from req.
Here is my server.js code (full version):
server.get('*', async (req, res, next) => {
try {
// some presettings here..
await Router.dispatch({ path: req.path, query: req.query, context }, (state, component) => {
data.body = ReactDOM.renderToString(component);
});
res.send(template(data));
} catch (err) {
next(err);
}
});
and Route's index.js (full version):
export const action = async (state) => {
const response = await fetch('/graphql?query={me{id,email}}', {
credentials: 'same-origin',
});
const { data } = await response.json();
// ...
return <Login title={title} me={data.me} />;
};
How can I pass my token from server.js to my fetch module? Or, maybe there are some better decisions?
First off, I hope you have found an answer by now!
Secondly, cookies are really just headers. If you need to send a cookie to authorize server-side requests, you can always just create the string that you need for the cookie value and send it as a header.
For an example, take a look at how this server-side node-fetch wrapper appends saved cookies to the outbound request: https://github.com/valeriangalliat/fetch-cookie/blob/master/index.js#L17

Categories

Resources