I am attempting to query a database and return the result to express before a render the result onto a template. Currently, I am using Axios and it sends a request to localhost:3000/api/endpoint. I have verified that the endpoint works through postman and it returns what I want from MongoDB.
My web server code looks like this:
app.get('/post/:id', (req, res) => {
axios.get(`localhost:3000/post/${req.params.id}`)
.then((response) => {
console.log(response);
res.render('post', { content: response.content });
})
.catch((err) => {
console.log(err);
res.render('404', { error: err });
});
});
For some reason, axios (or express) does not wait for the API to return the response, and instead jumps to the catch and returns the 404 page. I'm not sure why it behaves this way.
Note - the error that is returned is either: ECONNRESET or socket hang up
How can I fix it, so that express (or axios) waits for the API query to finish, before rendering it on the page?
Thanks to dhilt for the answer. Changing localhost to http://localhost fixed the problem, and now it's working flawlessly.
Related
I was working on admin registration and admin data retrieving react app. The registration works fine but retrieving admin data is crushing my backend. I have encountered this error when call the given endpoint from my react app. But when I call it from Postman it works very fine. And when I see the console on my browser my react app sends two calls simultaneously instead of one. On these calls my app crushes. If any one can show me how to solve this problem?
For backend = Node.js with express.js framework
For frontend = React
This is the error I am getting
node:internal/errors:465
ErrorCaptureStackTrace(err);
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot remove headers after they are sent to the client
at new NodeError (node:internal/errors:372:5)
at ServerResponse.removeHeader (node:_http_outgoing:654:11)
at ServerResponse.send (C:\Users\Momentum\Documents\The Technologies\Madudi-App-Api\node_modules\express\lib\response.js:214:10)
at C:\Users\Momentum\Documents\The Technologies\Madudi-App-Api\api\index.js:22:72
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
code: 'ERR_HTTP_HEADERS_SENT'
}
[nodemon] app crashed - waiting for file changes before starting...
This is how I setup my endpoint and changed the data to a string in order to get simple response but it crushes
const makeHttpRequest = (controller, helper) => {
const makeRequest = (req, res) => {
try {
var data = "Trying response";
res.status(200).send({ status: true, data: data });
} catch (error) {
console.log(`ERROR: ${error.message}`);
res.status(400).send({ status: false, error: error.message });
}
};
return { makeRequest };
};
const makeApi = ({router, controller, helper}) => {
router.get("/test", (req, res) => res.send("Router is Woking..."));
router.get("/admin/get_all_admins", async (req, res) => res.send(await makeHttpRequest(controller, helper).makeRequest(req, res)));
}
module.exports = { makeApi }
And this is the call from my react app
export default function GetAllUsers() {
useEffect(() =>{
try{
const response = axios.get('http://localhost:5000/admin/get_all_admins').then(async (response) => {
console.log('response ', response)
return response.data;
});
}catch(error) {
return [];
}
}, [])
I'm not familiar with this method of responding to requests, but in my own opinion the error you are facing happens when you're sending multiple response.
This may be the asynchronous nature of JavaScript, there by causing another request to be sent after the function is done.
You should also try to return the response, so that once it's done it cancels out of the function. You can use the example below
const handler = (req,res) => {
return res.status(200).json(data)}
This particular error happens when you try to send more than one response for the same incoming request (something you are not allowed to do).
You are calling res.send() more than one for the same request on your server.
The first happens in the makeRequest() function.
The second time happens in this line of code:
router.get("/admin/get_all_admins", async (req, res) => res.send(await makeHttpRequest(controller, helper).makeRequest(req, res)));
You can't do that. You get ONE response per incoming request. So, either send the response in makeRquest() and don't send it in the caller. Or, don't send the response in makeRequest() and just return what the response should be and let the caller send it. Pick one model or the other.
I am not familiar with this way of setting up the server. Looks strange to me. However, in router.get("/admin/get_all_admins" your sending a response which calls a function makeHttpRequest that also sends a response. Thus you get an error Cannot remove headers after they are sent to the client because you're sending a response twice.
I have been watching a tutorial on making a Rest API for Firestore which appears to work but I cannot figure out how to catch an error.
The code below basically uses an end point to retrieve a document id from the firestore database.
The client uses javascript fetch to call the API.
I am trying to workout how to return something back to the client from the API if the document id is not there. I thought I might get a 404 status returned but I always get status 200.
This is the API code I used
app.get("/api/read/:id", (req, res) => {
(async () => {
try {
const document = db.collection("users").doc(req.params.id);
let product = await document.get();
let response = product.data();
return res.status(200).send(response);
} catch (error) {
console.log(error);
return res.status(500).send(error);
}
})();
})
I'm fairly certain that the 404 message is for the server itself not being found (though I do need to brush up on my error codes).
However, if you're looking to check to see if a document exists there's a command specifically for that demonstrated in the examples in the firebase docs
Axios POST request sends data to Express sever but Error 404
Hello, world, I am trying to build a user authentication server for a project I am working on, but I am running into a problem trying to send a POST request to my Node.js Express server.
I want to send a POST request using Axios containing a username and password from the browser. But once sending the request it gives me a 404 Not Found error. The request has to go to http://website/api/login and my Node.js code should return either "authed" or "invalid". I tested the API inside Postman and that seems to be working. I also exported the request code from Postman and tested it with fetch API, xhr, and Axios, all returning the same result.
The server receives the data and handles it properly, but when I look in the Chromium debugger it appears that the request URL is just http://website/ and not http://website/api/login. I am honestly lost and I have tried what feels like everything, but I can't seem to make it work. Any help in pointing me in the right direction would be amazing! Thank you!
The code I use for the POST request is:
const username = document.getElementById("username").value;
const password = document.getElementById("password").value;
const data = JSON.stringify({"username": username, "password":password});
const config = {
method: 'post',
url: 'http://website/api/login',
headers: {
'Content-Type': 'application/json'
},
data : data
};
axios(config).then(function (response) {
console.log(JSON.stringify(response.data));
}).catch(function (err) {
console.log(err);
})
}
This is what I see in the Chromium debugger:
Headers
This is my Node.js / Express code:
app.post('/api/login', function (req, res, next) {
scriptFile.authUser(req.body, function (err, state) {
if (err) console.log(err);
else {
if (state) {
res.send("authed");
} else {
res.send("invalid");
}
}
});
})
Thank you for any help I can get.
I am stupid,
Breakdown of what happened:
Everything was working fine except that I put the input data and submit button inside a form, which will refresh the page...
I fixed it by changing the form to a div.
Hey checking your chrome console pic looks like your post request is hitting the root api address 'http://website/' and not the full path 'http://website/api/login
I have a code that does a GET request:
axios.get('/getsome').then((data) => onSuccess(data), (error) => onError(error));
The server returns 409 (CONFLICT) status. I expect onError to be called, but instead onSuccess is always called.
How is that possible? I saw with my own eyes in chrome dev tools that the status of response is 409.
UPD: I created a mock server with nodejs' express:
const express = require('express')
const app = express()
app.get('/getsome', (req, res) => {
res.status(409);
res.send(undefined);
})
And it hits onError callback! Now I completely do not understand: 2 different servers return same error code, but different callbacks fired.
try replace the position res to req, like this: app.get('/getsome', (req, res) => {
If you use the following code to make the get request it gives the correct error code and jumps inside the catch block. This is my standard way of handling errors in axios and it should fix your issue. Please give it a try.
axios.get('/getsome')
.then(response => {
console.log(response)
})
.catch(error => {
console.log("error")
});
The reason was following: in other place we use http interceptor to connect axios with nprogress library. After that connection was removed the error handling returned to normal.
So a general tip: in such cases check http interceptors and disconnect/fix them.
I am working on a React project, and after running into the problem described here: React-router urls don't work when refreshing or writting manually I implemented the "Catch-All" solution suggested in that link.
app.use("/", express.Router());
app.get("*", function (req, res) {
res.sendFile(path.resolve(__dirname + "/../build/index.html"));
});
This solved my refreshing problem, but it broke all of my fetch calls. For instance:
fetch("http://localhost:3000/api/login", {
method: "GET",
headers: {
"username": user.value,
"password": pass.value,
}
})
.then(response => response.json())
.then(function(data) {
console.log(data)
})
Which works fine if I comment out the above app.use and app.get lines, is giving me an error:
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
I think the promise returned by response.json() is being rejected, based on some console.log debugging I did. However, it seems that response is the same regardless of whether I comment out those lines. So I am not sure why it would fail.
In the following line, you are attaching empty router to / route.
app.use("/", express.Router());
So, when your client hits /api/login, it couldn't match to any route. Hence, it gets handled by * that send html file.
Since, /api/login is returning html file with 200 message, fetch tries to json-parse the html response. Thus, fetch throws an error.
Solution:
app.use("/", // valid router);