"Cross Origin Request Blocked" No solutions seem to work - node.js

Background
I'm building a MERN full stack application as a personal project. I am running the frontend client on localhost:3000 and the server on localhost:5000.
Problem
All of my API routes work as expected except for a GET request, router.get('/get-friends', ...) which queries the mongoDB to return a list of collection documents. Calling that get request on Postman returns the expected output. I decided to write a simple GET request that returns a method and it works just fine in my browser
When making the request the get-friends request in my browser, I get the following log:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/api/users/get-friends/. (Reason: CORS request did not succeed)
What I've Already Tried
Enabling cors in my Express server
Enabling cors preflight
Adding a proxy to the server from the client's package.json
Switching from Axios to vanilla JS's fetch() method
Turning off cors in my browser
I suspect the issue occurs when I make the request to the database from Express. I am really not sure how to solve this issue.
Here is the route in question:
router.get('/get-friends', (req, res) =>{
var species_ = req.body.species;
var gender_ = req.body.gender;
var neutered_ = req.body.neutered;
// query db
Friend.find({species: species_},{gender:gender_},{neutered:neutered_}).then((friends_) =>{
if(!friends_){
return res.status(404).send('query error, nothing returned');
}
return res.send(friends_);
}).catch((e) =>{
res.status(400).send(4);
})
});
Here is the project repo and the relevant files are:
https://github.com/edgarvi/foster-friends/server.js (Express server)
https://github.com/EdgarVi/foster-friends/blob/master/routes/api/users.js (Routes for the express server)
https://github.com/EdgarVi/foster-friends/blob/master/client/src/components/layout/SearchFriends.js (React component which calls the server)
I would gladly appreciate any help!

I have highlighted possible problems.
Reason: CORS request did not succeed
The HTTP request which makes use of CORS failed because the HTTP
connection failed at either the network or protocol level. The error
is not directly related to CORS, but is a fundamental network error of
some kind.
> In many cases, it is caused by a browser plugin (e.g. an ad blocker or
privacy protector) blocking the request.
Other possible causes include:
Trying to access an https resource that has an invalid certificate
will cause this error.
Trying to access an http resource from a page with an https origin
will also cause this error.
As of Firefox 68, https pages are not permitted to access
http://localhost, although this may be changed by Bug 1488740.
> The server did not respond to the actual request (even if it responded
to the Preflight request). One scenario might be an HTTP service being
developed that panicked without returning any data.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSDidNotSucceed

Thank you all for the help and the suggestions. After struggling through this for multiple days, I finally encountered a solution.
In my react client, I made the API call:
axios.get('http://localhost:5000/api/users/get-friends',
{
params: {
species: this.state.species,
gender: this.state.gender,
neutured: neutered_
}}
);
and then I changed the Mongoose query to look like:
router.get('/get-friends', (req, res) =>{
var species_ = req.query.species;
var gender_ = req.query.gender;
var neutered_ = req.query.neutered;
// query db
Friend.find({species: species_},{gender:gender_},{neutered:neutered_}).then((_friends) => {
return res.send(_friends);
})
});
I'm not exactly sure why these changes made my code finally work but once again, thank you all for the help and suggestions!

Related

Page not changing onClick using useNavigate in React?

I have a very basic UI for a login page:
Upon clicking the LOGIN button, the following methods gets called:
async function loginPatient(){
let item ={username:userName, password};
let result = await fetch("http://localhost:8000/users/login",{
method:'POST',
headers:{
"Content-Type":"application/json",
"Accept":"application/json"
},
body: JSON.stringify(item)
});
alert(result);
alert("breakpoint")
result = await result.json();
localStorage.setItem("user-info",JSON.stringify(result));
nav('/patient')
}
At this point I simply want it to change the page when the button is clicked. My API returns the following information from the database:
To test I did console.log("hello world") in the first line of the function and it works
However, If I run console.log("hello world") after the let result = await fetch(...) part it does not work. How can I test this to see why it's not working ?
Here are the errors from the console:
I did not write the API and do not know how Node works yet, I am just doing the front end for this
The issue is code is never reaching after fetch line, basically request is failing, the error on console is saying the due to CORS issue, the request failed, and in your loginPatient function, you have not handled the failed case, if you just wrap your fetch call inside try/catch block, you will see your code will fall into fail block, as api failed.
You need to enable CORS on your server or backend, Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources.
You can read more about cors at:
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Looks like your client is on some other domain or port(if your are developing locally) than your server. You need to enable CORS permission for your client url.
And if you are using express for your backend, you can check the following url to enable cors.
https://expressjs.com/en/resources/middleware/cors.html
And last thing why Postman is getting success response, because it is by passing this cors check, as Postman is making request from it's server to your direct server instead of browser.
First initialize you navigation variable as follows
const navigate =useNavigate()
then navigate to you specific route by returning you navigation variable as follows.
return navigation("/");
Happy Coding!

request to nodejs proxy: Provisional headers are shown

In my web app project, I came across a cross domain issue. The back-end API was deployed to the server, which providing the IP and port(We can assume the back-end API works well). And I am working on the front-end side, and still in the local development stage. So there is cross domain issue.
so I used a nodejs proxy and try to overcome the cross domain issue. For the nodejs proxy part, I am not the expert on that. Just get it from my teammates, who meet the same issue before.
So in my client side js code, I use axios library to send http request to the nodejs proxy as following:
axios.get('http://127.0.0.1:8888/service/delete/v1?id=5').then((response) => {
console.log(response);
}).catch((error) => {
console.log(error);
});
And the nodejs proxy will replace the 127.0.0.1:8888 part with the real API's IP and port, and send the request. That's my understanding about it.
so I run the nodejs proxy, which is listening on port 8888, and run my frond-end code in another console. But when I send the above mentioned request. I got the error as following:
GET http://127.0.0.1:8888/service/delete/v1?id=5 net::ERR_CONNECTION_TIMED_OUT
Error: Network Error
at createError (createError.js?f777:16)
at XMLHttpRequest.handleError (xhr.js?14ed:87)
and I debug the error deeper in the chrome devtool, and find the Provisional headers are shown in the header as following
I searched some previous article about this issue.It's said that the potential reason is the request is blocked.
But I can send other HTTP request successfully to other third party APIs. For example my mock data service Mockarro as following:
const key = 'mykeyxxx';
const url = `http://www.mockaroo.com/api/generate.json?schema=firstapis&key=${key}`;
axios.get(url).then((response) => {
console.log(response);
});
So my the previous request is blocked. I am very confused. My guess is the issue is from the nodejs proxy part? Right?

Express wont match url to route when coming from remote server

I'm setting up a site that posts to a remote server. The user performs some steps on this remote server and when the user is done. The server issues a get request with a bunch of query parameters to my server.
The thing is that this request never arrives at the controller method it is supposed to.
I have a custom middleware that intercepts all requests and i am doing some logging in there, i can see there every time this request arrives to my server but express doesn't seem to match it to the controller.
However if i go into my browser and do the request from there with the exact same path and query string it works fine.
I thought maybe the remote server was using a proxy so i enabled trust proxy in express but that didn't make any difference.
I have tried changing the route path and that didn't make a difference.
I don't know what code would be helpful since it is pretty standard express code. I have tried putting the route before all the middleware and the request still bypassed the controller and was logged by my logging middleware.
I'm completely baffled, anyone got any idea what could be causing this?
EDIT:
Here is some of the code I'm using. This is not the exact setup I'm trying but I have tried to make it work this way to rule out my routing logic and this example has the exact same problem. I tried putting the app.get above the middleware and the request from the external server still bypassed the app.get and went directly to the middleware.
app.use(function(req, res, next) {
console.log('path', req.method, req.path, req.query);
});
app.get('/payments/success', function (req, res) {
console.log('SUCCESS', req.query);
res.status(200).send();
});
Here is the result of the middleware logging a request arriving from the remote server(i removed the variables logged from the request query because it is sensitive information, they are returned just the way they are supposed to):
path GET /payment/success {
variable: 'variable",
}
If anyone needs any more information from the request object i will provide it.

Getting proxy error when using "gulp serve" when API returns 204 with no content

I am using Gulp to develop an Angular application generated by Yeoman's gulp-angular generator. I have configured it to proxy requests to /api to another port, the port my API is listening on. That port is actually forwarded via an SSH tunnel to an external server.
Here is the config generated by Yeoman that I have edited for my own API:
gulp/server.js
'use strict';
var gulp = require('gulp');
var browserSync = require('browser-sync');
var httpProxy = require('http-proxy');
/* This configuration allow you to configure browser sync to proxy your backend */
var proxyTarget = 'http://localhost:3434/api'; // The location of your backend
var proxyApiPrefix = 'api'; // The element in the URL which differentiate between API request and static file request
var proxy = httpProxy.createProxyServer({
target: proxyTarget
});
function proxyMiddleware(req, res, next) {
if (req.url.indexOf(proxyApiPrefix) !== -1) {
proxy.web(req, res);
} else {
next();
}
// ...rest of config truncated
stdout
[BS] Watching files...
/Users/jason/dev/web/node_modules/http-proxy/lib/http-proxy/index.js:114
throw err;
^
Error: Parse Error
at Socket.socketOnData (http.js:1583:20)
at TCP.onread (net.js:527:27)
I get the above error when my application attempts to hit a particular API url which sends back a response of 204, no content.
url structure: POST /api/resource/delete
(API doesn't support actual DELETE http method so we POST to this endpoint)
Response: 204 No Content
The API is also in development and is being served via the built in PHP web server. What the server is telling us is that the client (aka Node in this case because it is the proxy) is hanging up before PHP can send the response.
I thought perhaps it was just choking on the fact that there was no content. So, we created a second endpoint that also returned 204 No Content and it seemed to work fine. But, to be fair, this issue appears to be intermittent - it works sometimes and sometimes it does not. It's very confusing.
As far as we can tell, it only happens on this delete URL, however. I am pretty new to Node and am having a very hard time figuring out what the issue is or where to look. Does anyone have any clues or has anyone seen this before?
It turns out that the developer of the API was sending me content along with his 204 when he shouldn't have been - some debug code left in. The HTTP parser that node-proxy uses was then reading that content from the buffer at the beginning of the subsequent request and then throwing an error because it wasn't seeing a properly formed HTTP request - since the first thing in the buffer was a PHP var_dump.
As it happens, my front end app did the delete call and then refreshes another object via the GET request. They happen so fast that it seemed like the DELETE call killed the gulp server, when it was actually the GET command afterwards.
The http-proxy module for node explicitly does not do error handling, leaving the onus on the end user. If you don't handle an error, it bubbles up into an uncaught exception and will cause the application to close, as I was seeing.
So, the fix was simply:
gulp/server.js
var proxy = httpProxy.createProxyServer({
target: proxyTarget
}).on('error', function(e) {
console.log(JSON.stringify(e, null, ' '))
});
The console will now log all proxy errors, but the process won't die and subsequent requests will continue to be served as expected.
For the error in question, the console output is:
{
"bytesParsed": 191,
"code": "HPE_INVALID_CONSTANT"
}
Additionally, we've fixed the API to honor its 204 and actually, you know, not send content.

Socket.io + Express CORS Error on localhost (not allowed by Access-Control-Allow-Origin)

I have a working node.js Express server to which I would to add socket.io support (allow javascript clients to connect via socket.io). I can connect to the express server via a Javascript $.get(), but the socket.io.connect() command fails due to a CORS error.
My testing machine is OSX with Apache to serve the client, thus port 80 is taken, so I have node.js/express running on port 8888. I added socket.io per the documentation:
var exp = express();
var server = require('http').createServer(api.server);
exp.listen(8888);
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket) {
console.log('connection');
});
I properly see "info: socket.io started" in my node.js logs.
Then, on the client, I attempt to connect to the server...
this.socket = io.connect('http://localhost:8888');
this.socket.on('connect',function() {
socket.emit('install','test');
});
However, I'm getting a CORS error in the console in Chrome:
XMLHttpRequest cannot load http://localhost:8888/socket.io/1/?t=1358715637192. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
HOWEVER, THIS works fine!
$.get('http://localhost:8888',function(e,d){
console.log(e,d);
});
So I double checked my headers, for both localhost:8888 and localhost -- both are properly returning the headers which (should) allow for the cross-domain requests...
Access-Control-Allow-Origin: *
Any ideas?
CORS is a very tricking thing to get working (or at least it was for me). I recommend this resource here: http://enable-cors.org/
Following what they do very carefully helped me. I also found that different browsers gave different visibility over the CORS request/responses which helped.
I found that Chrome was easier to get working than firefox, but firefoxes tools such as firebug, were quite nice to work with.
My gut feel from your information is that you might need your request to have an X-Request-With in your request attributes.
I also found using fidler to send the http requests allowed me to narrow my problems down to the server side initially and get that working. You will find browser enforce CORS, but something like fidler doesn't and thus provides another way of inspecting what is happening.
I definately recommend trying to break the problem in half so that you can see if it is server side or client side that is not behaving how you expect.
My problem was related to returning the same CORS response for the OPTIONS header as the POST or GET. That was wrong. Chrome allowed it. Firefox didnt. Any options request that is sent out will be sent out once, then in the future it will be cached and not resent (Which caused alot of confusion for me initially). For the options request you just need a standard response saying its ok to proceed, then in the post or get response i believe you want your cors responses there only.

Resources