How can I fix the "Unhandled Rejection (error): Network error" obtained using axios in React - reactjs

I'm creating a React Application, and it is hosted on localhost:3000. I want to fetch data from a .NET Core Application hosted on localhost:5001. I'm using axios library to make http requests.
The function in which I make the request is:
async componentDidMount() {
const data = await axios.get("http://localhost:5001/api/gateways");
console.log(data);
}
The obtained Error is "Unhandled Rejection (Error): Network Error".
I tried to test the API with Postman and it works, as well as accessing it from the browser and it works too.
At the same time I tried to consume data from another API, this time hosted on an online server, and it worked perfectly, that means, the problem must be between two applications hosted on the localhost.

I fixed this issue by adding an Access-Control-Allow-Credentials header to HTTP responses in .NET CORE application. This header tells the browser that the server allows credentials for a cross-origin request.
Its necessary modify Configure method at Startup.cs fileadding the following code:
app.Use(async (context, next) =>
{
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
await next.Invoke();
});
And, it is also necessary modify ConfigureServices method with:
services.AddCors(c =>
{
c.AddDefaultPolicy(options => options.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod());
});

Related

Cors issue i also set the proxy in pkg.json due to cors and set the api according to it but this error is not remove

GET http://localhost:3000/api/fetch?search=12312321 404 (Not Found)
cors issue in Reactjs and node js
i use the proxy method in Reactjs but can't get rid from it please help me
proxy
"proxy":"http://localhost:5000/"
tried both
"proxy":"http://localhost:5000"
express
RegisterRoute.route('/fetch/:id').get( ( req , res) =>
{
console.log("called by someone ",req.params.id);
res.send("okey will");
});
Reactjs function which will call the backend api
FetchNotification(){
axios({
'method':'GET',
'url':'api/fetch',
'headers': {
'content-type':'application/octet-stream',
'x-rapidapi-host':'example.com',
'x-rapidapi-key': process.env.RAPIDAPI_KEY
}
,
'params': {
'id':'12312321'
},
})
}
when i simply call axios.get it perfectly work but when i give params to it it gives the error xhr:178 404 not found
a simple server which also returns the same result
const express = require('express');
const cors= require('cors');
const app= express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
// parse application/json
app.use(bodyParser.json());
app.use('*',cors());
app.get('/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
});
app.listen(5000);
I can see that you're using Nodejs as server side. So, you can try changing following line
app.use('*',cors());
to
app.use(cors());
If this doesn't solve the issue, you can try adding a google chrome extension for CORS (Most probably). In this way, you'll not need any proxies being set for running servers.
Also, you need to do a small change in URL, instead of calling
'url':'api/fetch'
you need to provide an id in your call, because the backend api is accepting a parameter
'url':'api/fetch/some_id'
I feel there are multiple issues. I'll try to address them one by one.
Firstly, if you are proxying your requests correctly (which I think you are as per your package.json), then you'd not require the cors package. So you can get rid of that package.
Read more about why you shouldn't let all incoming request bypass the CORS check from security point of view -> Is it safe to enable CORS to * for a public and readonly webservice?
Now secondly, the url which you've specified on the frontend is 'url':'api/fetch', which means browser will make a call to http://localhost:3000/api/fetch?search=12312321 which it correctly did as seen in your error statement for 404.
Specifying the proxy as "proxy":"http://localhost:5000" in package.json means that now you are making requests to http://localhost:5000 instead of http://localhost:3000, but the browser would still think its http://localhost:3000. That's the whole purpose of proxying and how you kinda fool browser to do CORS without throwing any error.
But because on your server, you are listening to app.get('/fetch/:id',(req , res) instead of app.get('api/fetch/:id',(req , res), it doesn't matches with this URL as you have not explicitly handled requests starting with /api in some separate router module either.
So you should either update the url in the axios call to url':'/fetch while the proxy value in package.json is "proxy":"http://localhost:5000" or url':'fetch and "proxy":"http://localhost:5000/" respectively. Notice how i've used the /
OR
You can update the URL on the express end to app.get('api/fetch/:id',(req , res)
Lastly, whenever you receive a request, you need to return some value(string or JSON or even status code) as result.
In your case, you've simply console.log("calling",req.params.id); and didn't send back any response to the UI.
So even if your 404 would resolve after fixing the URL, you'd bump into request timeout error (408) as your UI will keep waiting for a response from the server while you didn't send any.
So you should do something like this maybe:
app.get('api/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
res.send("It worked");
});
Notice how there's a response being sent back -> https://expressjs.com/en/starter/hello-world.html
If you don't want to send back a response, then you can simply return status like 200, 504 etc.
if you apply below code in backend/server i thing it will debug.
app.get('api/fetch/:id',(req , res) => {
console.log("calling",req.params.id);
res.send("It worked");
});

Here Maps Geocode API leads to Cross-Origin error

I use the first example here in order to get the geo coordinates based on an address:
https://developer.here.com/documentation/maps/3.1.15.1/dev_guide/topics/geocoding.html
My JavaScript coding looks almost the same as in the official documentation:
var platform = new H.service.Platform({
'apikey': 'HERE IS MY API KEY'
});
// Get an instance of the geocoding service:
var service = platform.getSearchService();
service.geocode({
q: 'Berlin'
}, (result) => {
result.items.forEach((item) => {
console.log("test");
});
}, alert);
However, when the geocode request is sent, I get the following error:
Access to XMLHttpRequest at '**https://geocode.search.hereapi.com/v1/geocode?xnlp=CL_JSMv3.1.16.1&apikey=[HERE IS MY API KEY]&q=Berlin**' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
The API key is sent correctly, why do I still get the CORS error?
If I enter the request URL manually in the browser, I get a response and everything is fine.
Yes, the server will help with the issue. I'm here to suggest the alternative.
You can do the geocoding with the HERE Maps REST as well see docs — https://developer.here.com/documentation/geocoding-search-api/dev_guide/topics/endpoint-geocode-brief.html.
Since not all the browsers historically support the CORS (learn more about the CORS — https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) there is an approach, called JSONP. See some JSONP explanation Here Maps related in the old docs https://developer.here.com/documentation/places/dev_guide/topics/request-cross-domain-js.html.
Eventually the https://www.npmjs.com/package/jsonp npm package could be a good follow up and we can get something like this after installing the package (npm install jsonp --save).
import jsonp from 'jsonp';
jsonp('https://geocode.search.hereapi.com/v1/geocode?q=5+Rue+Daunou%2C+75000+Paris%2C+France&apiKey=my-api-key',
null,
(err, data) => {
if (err) {
console.error(err.message);
} else {
console.log(data);
}
});
This works great from my experience.
If you are testing this code by opening the file in the browser, you may get this error. I suggest using a local server for testing.

Opening up Rails API to users within a closed network

I am attempting to run a React/Rails Website locally for 2-3 users within a closed network. Currently, the users can reach the React portion (I have that set to port 80). The problem is, the API calls I have set to my Rails backend are all on localhost:3001 and the users have zero access to that database when I try to submit HTTP requests.
I know it's a CORS issue but I thought the code below would allow any domain to make the necessary request.
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
Server side work is not my forte, so I may be missing something glaring. Any idea how to open up that backend so the networked users can make API Calls on their end?
React is on this ip: http://192.168.2.70:80/
API calls on this port: 3001
Example API call from front end (works on host computer; not on other users):
getData = () => {
axios.get('http://localhost:3001/api/v1/pickup_deliveries')
.then((response) => {
this.setState({
apiData: response.data})
})
.catch((error)=>{console.log(error);});
}
The Problem
Unless I missed something, it looks like you're making a simple mistake that you're going to smack yourself for.
Typically, a CORS issue in a JavaScript application would yield a CORS/pre-flight request error error in your browser's JavaScript console.
The Misconception
The JavaScript that makes up a React application is downloaded by the client (i.e. your users). After that, the fetch call is executed on the client's computer. The fetch request doesn't originate from the server, but rather from the remote end.
It works on your computer because both React and the Rail API are hosted on your computer, so localhost:3001 resolves correctly. However, on your users computer, the React app attempts to find a service running on port 3001 on their computer.
Initial Solution
You need to tell React to reach out to the IP server that's hosting the API, like this:
getData = () => {
axios.get('http://192.168.2.70:3001/api/v1/pickup_deliveries')
.then((response) => {
this.setState({
apiData: response.data})
})
.catch((error)=>{console.log(error);});
}
Long Term Solution (for deployment)
In the future, look into dotenv, which will allow you to set React environment variables. You could have a .env.local file, and a .env.production file.
In the local file, you could put:
REACT_APP_BACKEND_SERVER=http://localhost:3001
and in the production on you could put:
REACT_APP_URL=http:/<server_ip>:3001
Then, in your program, do something like:
getData = () => {
axios.get(process.env.REACT_APP_SERVER_URL + "/api/v1/pickup_deliveries")
.then((response) => {
this.setState({
apiData: response.data})
})
.catch((error)=>{console.log(error);});
}
This will automatically resolve to localhost when serving React using npm run start and then resolve to <server_ip> when you are serving the static files generated by npm run build.
Feel free to comment on this answer. I would be happy to answer any other questions you have. Welcome to React!

How do I fix a network error received from axios response reactjs

I'm making a post request using axios in reactjs after users login. Here it is:
axios.post('https://localhost:3000/api/login/authentication', {
email: email,
password: password
})
.then(response => {
this.props.history.push('/Main')
})
.catch(error => {
console.log(error)
})
It goes in the error and I log it to the console. This is what I get:
Error: "Network Error"
createErrorhttp://localhost:3000/static/js/0.chunk.js:26742:15 handleErrorhttp://localhost:3000/static/js/0.chunk.js:26293:14
Also in case it's any help, I get this warning before the error:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://localhost:3000/api/login/authentication. (Reason: CORS request did not succeed)
Can anyone please help me solve this issue? Thanks in advance!
If you're using a front-end application that makes request to a back-end API, you need to include certain headers in the API server if the API server is running on a different port.
For example, if you're serving a ReactJS application with webpack in development mode, webpack acts as a server, sending the reactJS application to the client. Then, making requests to the API server will require that the API server, running on a different port, include Access-Control-Allow-Origin headers in all http responses.
Basically, before generating every response, you need to set 'Access-Control-Allow-Origin' to localhost:<port you visit in the browser>.
In a basic express app, you can paste this in your app.js file, for example:
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', 'http://localhost:3001');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
next();
});
Note: If you may need to change http://localhost:3001 to match the port you visit in the browser.
EDIT: OP is not using express, but is using Webpack. The question is: What is an express-agnostic solution?
Answer: The solution is still the same: regardless of what API server you are using, just set the response headers for every response.
There is another solution that involves Webpack, though:
In the package.json file of your front end code that's being served with webpack, add the following: "proxy" :"http://localhost:<port API server is running on>"
For example, is webpack is serving your front end app to localhost:3000 and your api server is running on localhost:3001, then the proxy in package.json would be:
"proxy":"http://localhost:3001"
You can add the CORS header in webpack dev server config as follows:
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
},
This will add these two headers in your response. Hence solve your problem. However, when your services run on a different server other than your local machine, these headers need to be added in server response.
The very first thing that i am figuring out in your code is that you are using 'https' but it should be only 'http'to make request, because local host uses http.
2)This might be due to cors, Before making any requests , the browser sends a pre-flight request to the API server to know that "This website has been allowed to access your resources or not", so using cors and specifying origin which can access API resources will solve this problem.

Unable to call to API after deploying app to Heroku

I've made a weather app that makes an API call to freegeoip to locate your current location's coordinates, and then using those coordinates to connect to openweathermap API to fetch your current location's weather.
In development the app worked perfectly fine. But after deploying to Heroku, I seem to get what looks like a CORS error?
Console logs:
Mixed Content: The page at 'https://weather-react-drhectapus.herokuapp.com/' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://freegeoip.net/json/'. This request has been blocked; the content must be served over HTTPS.
Link to Heroku app
EDIT:
Changing to https seems to work for the freegeoip API (https://freegeoip.net/json/), but doesn't work for the openweathermap API. This is the full console log I get:
GET https://api.openweathermap.org/data/2.5/weather?appid=95108d63b7f0cf597d80c6d17c8010e0&lat=49.25&lon=4.0333 net::ERR_CONNECTION_CLOSED
bundle.js:16 Uncaught (in promise) Error: Network Error
at e.exports (bundle.js:16)
at XMLHttpRequest.d.onerror (bundle.js:16)
Google Maps API warning: NoApiKeys https://developers.google.com/maps/documentation/javascript/error-messages#no-api-keys
Google Maps API error: MissingKeyMapError https://developers.google.com/maps/documentation/javascript/error-messages#missing-key-map-error
Just change API endpoint to use https instead of http.
https://freegeoip.net/json/ works well ;)
Update
Your updated question contains one more request. Unfortunately, api.openweathermap.org is not available over HTTPS. Thus, you need to reach it thru proxy under your control and forward response to your client. For more info, see this answer
If you apply this middleware it should start working correctly
app.use(function (req, res, next) {
if (req.headers['x-forwarded-proto'] === 'https') {
res.redirect('http://' + req.hostname + req.url);
} else {
next();
}
});

Resources