request to nodejs proxy: Provisional headers are shown - node.js

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?

Related

Socket IO allows CORS request from curl, but not from client application

I am making an application in which i have a node backend, and an angular frontend.
I am using socket.IO to communicate between my client and server.
I was facing CORS issue, which i solved (tried to) as:
const io: SocketIOServer = new SocketIOServer(server, {
cors: {
origin: true
}
}); // only for development
But still, upon making my request from my client app (running in another port) gives me CORS issue.
So i went to my terminal, and made a request with curl,as shown here:
me#Desktop:~$ curl "http://127.0.0.1:5000/socket.io/?EIO=4&transport=polling&t=NV5sBAn"
0{"sid":"jAhPIEEkdy8EY8I_AAAD","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}
This suggests me that curl is being able to access the server, and is not facing CORS issue.
In my client, i am trying to connect to my server as:
socket = io.connect('http://locahost:5000'); // server running at port 5000
Help me with my issue, so i can connect with my server.
Also on a sidenote: If the version of server.io in the app is 3, the curl request to the server is also failing. only upon server.io version 4, the curl request is passing.
The error in firefox if that helps:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://locahost:5000/socket.io/?EIO=4&transport=polling&t=NV5vi1_. (Reason: CORS request did not succeed).
EDIT: my issue is not being able to connect to the server with client. I showed the curl because it was suggested in the socket.io cors configuration webpage.
Because socket.io initiates its connection with plain http requests, it is subject to CORs restrictions. CURL does not enforce CORs restrictions (like the browser does) so that's why you don't see it there.
You have a couple options:
You can enable this specific CORs request in your server to permit it.
You can specify the {transports: ['websocket']} option for your socket.io connection in the socket.io client code that initiates the connection. This will tell socket.io to immediately start with a webSocket connection which is not subject to CORs.
Curl does not implement CORS security restrictions, thus it will always be able to connect. You have different ports for your frontend and backend which are considered different CORS origins. So you either need to set your allowed origins correctly on your server and make sure it handles the pre-flight requests, or have the process serving your frontend proxy requests to the backend so that everything is on the same url from the browser’s point of view
Apprrently, the issue was:
socket = io.connect('http://localhost:5000');
changing this to:
socket = io.connect('http://127.0.0.1:5000');
worked!! I have no idea why this name was not getting resolved!!

Failed to load resource: the server responded with a status of 431 (Request Header Fields Too Large)

when i am trying to use my NodeJS api from the react app(building a MERN stack app) i get the error mentioned in question
"Failed to load resource: the server responded with a status of 431 (Request Header Fields Too Large)"
the api is working fine from postman
const onSubmit=async(e)=>{
e.preventDefault()
if(password!==password2){
console.log('passwords dont match')
}else{
const newUser={
name:name,
email:email,
password:password
}
try {
const config={
headers:{
'Content-Type':'application/json'
}
}
const body=JSON.stringify(newUser)
//axios has been set up as proxy
//http://localhost:3000
//we dont need to add the above to url
const res =await axios.post('/api/users',body,config)
console.log(res.data)
} catch (error) {
console.error(error.response.data)
}
}
}
The HTTP 431 Request Header Fields Too Large response status code indicates that the
server refuses to process the request because the request’s HTTP headers are too long.
The request may be resubmitted after reducing the size of the request headers.
431 can be used when the total size of request headers is too large, or when a single
header field is too large. To help those running into this error, indicate which of the > two is the problem in the response body — ideally, also include which headers are too
large. This lets users attempt to fix the problem, such as by clearing their cookies.
Servers will often produce this status if:
The Referer URL is too long
There are too many Cookies sent in the request
In my case I was sending too many cookies because localhost:4200 was used as the domain of 3 different projects ... The solution (delete useless cookies)
Hope this helps...
I was getting this error when I used the same local port in the proxy destination as the port of the React app by accident. This created an internal forwarding loop, resulting in "Request Header Fields Too Large".
I was getting that error when forgetting to run my server first, before running React app.
I used a knex.js and express.js based simple back end and forgot to initialise it before starting React. Now it all works fine.
Clean your browser cache or Open with an incognito window.
Go to chrome dev tool > Application > Cookies,
Clear the cookies, and you are ready to rock!
You must be following Traversy Media !
remove proxy statement from package.json and write node url in axios call
After I used chrispytoe's suggestion to debug, I knew the problem is related to wrong URL, but not axios or React. To be more specific, something related to the URL on the server side.
Here's what I would suggest to help debug. On the server side in that
route, do console.log(req.headers). Then make the request from
postman, then make it from your react app and see what the differences
are. – chrispytoe
How I fixed this problem is to make sure the proxy server port in my client's packcage.json the same as my server.js' port number. Add the line below to the end of your's client's package.json (before the last "}").
"proxy": "http://localhost:5500"
Next, set your server.js' port the same as your proxy's port:
const PORT = process.env.PORT || 5500;
In addition, it doesn't matter what port you configure your client to use. It has nothing to do with the server and its proxy server.
Hope my 2 cents help. Please feel free to correct me. Thanks.
This error arises when the API server port you inputted in your front-end proxy(e.g "proxy":"http://localhost:5000/") isn't the same as the port on the server.
when you get back to the front end and start building React hooks, you'll have a to do a bit of jumping around on a PC
install cross-env lib:
npm i --save-dev cross-env
alter your start section in package.json
"start": "cross-env PORT=8000 react-scripts start",
allow you to declare the start port of the project to avoid conflict with other libs, in this case the create-react-app
431 HTTP response status code is sent from the server when client's HTTP Header is greater than the server's accepting HTTP Header limit. Maximum size of HTTP Header for well-known web-server is provided here.
This makes complete sense that the API is working fine from Postman and not browser; As there won't be any residue cookies present in Postman.

"Cross Origin Request Blocked" No solutions seem to work

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!

Can I make a request to an HTTP API server without opening myself up to vulnerabilities?

I am building an API server using Node.js and Express. My server has a route which requires important data from a 3rd party, so I would like to make a request to their API using axios.
My problem is that the 3rd party's API endpoints are http://..., not https://. As a result, I get the following error:
(node:7088) UnhandledPromiseRejectionWarning: Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: api.<3rdpartysite>.com. is not in the cert's altnames: DNS:www.<3rdpartysite>.com, DNS:<3rdpartysite>.com
I know that it is up to the 3rd party to fix their API so I can access it via HTTPS. I have reached out to the API developer repeatedly for weeks with no response.
I can make things work by setting the environment variable NODE_TLS_REJECT_UNAUTHORIZED=0 , but I know that opens up significant security risks.
Here is the code I am currently using to make the request:
app.post("/api/v0/myRoute", async (req, res) => {
const response = await axios.get(
`http://api.<3rdpartysite>.com/v0/theirRoute?
apikey=${keys.thirdpartysite}`
);
console.log(response);
});
Changing the http above to https gives me the exact same error message.
I want to make this request without putting my own API server at risk. Is there a way?

How to add facebook authentication to my react app?

I'm using express as backend. I implemented facebook authentication at the backend.
router.get('/login/facebook',
passport.authenticate('facebook',{scope:['email']}));
router.get('/login/facebook/callback',
passport.authenticate('facebook',{
successRedirect : '/home',
failureRedirect:'/'
})
);
Now I want to call this through my react app, so that when the user lands up at home page, first he should be authenticated by facebook then only he can see homepage. How can I do this ?
I tried using react-router, but I can't understand how to call backend using react-router.
I also fetched /login/facebook using fetch command :
componentDidMount(){
fetch("127.0.0.1:3001/login/facebook");
But it gave me CORS error.
My react app is at 127.0.0.1:3000 and express server at 127.0.0.1:3001.
If this issue is only in dev mode, then Daniel's answer is correct.
In any case, I recommend to avoid calling the :3001 api directly from the :3000 app. Here's what I would do.
I will edit the fetch call as follows,
componentDidMount(){
fetch("/login/facebook");
}
This call will be received by the backend which serves the react application.
Now there are three cases,
Case 1: Your file serving app will have a proxy method which can forward requests to an API. For example read it here
Case 2 This is my Recommended approach. I would simply write the authentication logic in the :3000 server and only use the :3001 API for handling business logic of the app.
Case 3: If you have a backend app (:3000), say written using expressJs, you can forward the request to the :3001 API. Here is a sample code for that,
client.send({
method: req.method,
path: req.url,
data: req.body,
params: req.params
}).then( (response) => {
// Something
}).catch( (err) => {
// Handle error
});
Here the client is a module which uses the request module to make HTTP calls.
You can implement the above call as an express middleware to use it for all HTTP calls.
There are several options:
If you are using webpack dev server, you can set up a proxy to your api. See here
You can temporary disable cors validation during development. See here

Resources