Client (react) cannot access response from Server (express) - node.js

I'm working on a post route for an express.js server. I've got a validation function that if not passed, returns a 400 code with message. The client (React), receives the 400 code, but I cannot access the message sent by the server.
This is within the POST in express:
const { error } = validate(req.body);
if (error)
return res
.status(400)
.send(error.details[0].message);
This is the submit routine in React:
doSubmit = async () => {
const { username, password } = this.state.data;
const result = await login({ mail: username, password });
console.log('result', result);
};
Login is only a wrapper for axios.post method:
export async function login(user) {
try {
return await http.post(apiEndpoint, user);
} catch (ex) {
console.log(ex.message);
return ex;
}
}
Currently, the code works as it is. Submitting an invalid input, such as a password below 5 characters, i get the following in the client:
POST http://localhost:3000/api/auth 400 (Bad Request)
Request failed with status code 400
result Error: Request failed with status code 400
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:78)
at XMLHttpRequest.wrapped (raven.js:363)
However, if I change the status code sent by the server to "200", I get:
result {
full response here along with data property..
data: ""password" length must be at least 5 characters long"
}
I've been reading the Express documentation. It doesn't say anything about not sending the response if the code is 400 (although it makes sense to send nothing if bad request). I've also toyed a bit with 'body-parser' but didn't get different results.
However, if I test in postman, it works like a charm! With same input, i get the status code and the message.
Finally, it's ok to validate both the input sent (client) and the data received(server) right? If so, let's say the client is OK with the input, but the server is not. Should the server respond with whatever the problem is (what i'm trying to achieve), or simply say 'ERROR' (current scenario)?
Thank you.

Axios code example, may be given code fix your issue. The issue is with your parameters.
axios({
url: '/login',
method: 'post',
params: { username: 'cedas', password: 'fredsed' }
}).then(response => {
resolve(response)
})
.catch(error => {
reject(error)
});
})

Well, in the end, the problem was accessing ex.message, instead of ex.response ... Cheers.

Related

Axios POST request sending but not being recieved

I know this has been asked before but any solutions I've tried have failed to get results so far. I'm new to Axios and I'm trying to test sending a POST request, and it seems like the request is indeed sent, but it never ends up actually being received, despite showing a 200 OK status code. I've been troubleshooting a while, but no amount of changing headers or fiddling with the server seems to have changed anything.
Sending Request
handleSubmit(event){
event.preventDefault();
var myObj = {
email: this.state.userEmail,
password: this.state.userPassword,
failedLogin: this.state.failedLogin
}
// validate login
axios.post("/login", myObj)
.then(function(response){
console.log(response.data.test);
})
.catch(function (error) {
console.log(error);
});
}
Receiving Request
The alert with "receive" is never executed.
userRoutes.route("/login").post((req, res) => {
console.log("sent");
res.send({test: "test"})
});
And my requests/responses and console:
request
response
console
Axios signature for post is axios.post(url[, data[, config]]). So your object should be written as 3rd parameter. Also, your post url must be complete. Otherwise you will get invalid url error.
Sending Request
axios
.post("http://localhost:3000/login", null, yourObj)
.then((res) => {
console.log(res.data.test);
// Result: test
})
.catch((err) => console.log(err));
Receiving Request
app.post("/login", (req, res) => {
res.status(200).json({ test: "test" });
});
Sure enough, as #Phil and #trognanders suggested, the problem was because my Express middleware was configured incorrectly, hence not an Axios problem.

Why is NodeJS crashing when API returns 400 HTTP status code?

I was working with this API and everything was fine until I've tried POST method.
Now what happens is, when I try to send data from postman, NodeJS app crashes, displaying this error: HTTPError: Response code 400 (Bad Request) and pointing that error is called in the catch part.
So thing is, when I directly send post request to the API directly (not with my localhost server) it returns 400: Bad request with message that data is not correct. Now everything is okay when I send it directly, but when I try to call the API with my localhost it throws that error.
The error is throw from the call: got.post(...) which uses this library:
https://www.npmjs.com/package/got
Is it possible to make that call and get the 400 response without getting an error raised from the call?
methods.ts
export const addReservation = async (postData: object) => {
const url = API_URL + '/reservation';
try {
const response = await got.post(url, {
json: { ...postData },
responseType: 'json',
});
console.log(response.statusCode); //no success, jumps to the catch block
return response.body;
} catch (error) {
throw new Error(error);
}
};
reservation.ts
export const reservationHandler = async (req: Request, res: Response) => {
let postData = req.body;
let response = await addReservation(postData);
return res.status(201).json(response); //if all is OK it will return 201, but if not 400
};
So I've tried catching the status code in addReservation but no success. I was having idea by handling cases of status codes 400 or 201, but only proceeds with try block if the status is 201, but if it is 400, it crashes the app.
You have to set throwHttpErrors to false in got options.
https://github.com/sindresorhus/got#throwhttperrors

Problem with redirect using 'fetch' from frontend page

I am using the following JS in a webpage to send information to a Node.js server upon 'clicking' on an image in the webpage, I am having trouble with the 'redirect' once the 'fetch' is executed:
fetch('/members/pages/callup', {
method: 'post',
headers: {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body: JSON.stringify({name: splits[1], presence: available, str: 'Some string: &=&'})
})
.then(function(res) {res.json()})
.then(function(res) {
if(res.response) {
redirect: window.location.replace("/members/pages/" + splits[1]);
} else {
alert("Error in the response");
}
})
.catch(function(err) {
alert("Error in the fetch call..." + err);
})
The fetch seems to properly send the 'body' data to the server. However I am getting the following error: "Error in the fetch call...TypeError: Cannot read property 'response' of undefined"...
The server performs a database call using the information sent by the frontend, and I thought all I needed to do was to send a "200 (OK)" response back...here is the server code:
app.post('/member/pages/callup', jsonParser, function (req, res) {
console.log("I RECEIVED FROM CLIENT THE FOLLOWING:");
console.log(req.body); //works fine, prints output from frontend 'fetch' to console...
db.lookupMember(req.body.name)
.then(function(foundUser) {
console.log('Async success!', foundUser); //works fine, prints database info to console...
if (typeof foundUser != "undefined") {
res.sendStatus(200); //trying this to 'reply' back to 'fetch' in frontend...is this not correct?
} //'foundUser' is NOT'undefined'...
})
.catch(function(error) {
console.log('UNABLE TO RETRIEVE MEMBER INFORMATION FROM THE DATABASE...' + error);
res.redirect('/'); //route to splash page...
});
})
Any suggestions appreciated, this has gone from a minor irritant to a major problem. I thank you in advance.
There are few issues in the code. If fixed, code should work fine.
You forgot to return res.json() from the function at one place. Make it return res.json() and it will work fine (Inside fetch, 1st then). Due to not returning, res is undefined which is giving the error
You are trying to use res.response but res is not send as a proper json from node server. This will fail at res.json(). You should be doing something like res.send({response: true})
After the if loop in server there is syntax error. It needs to be redirect = instead of redirect:. Also redirect is not declared anywhere which. (Note: you might not need redirect variable here, simply window.lo... should also work)
Note: Have updated the original answer after having the discussion with OP

Cannot GET from Express.js PUT route, why?

Is there any reason you cannot execute a GET request from inside an Express.js router.put()?
I have two routes. The exact same api call works in a router.get() route and hangs in the router.put().
I've confirmed that
This works:
router.get('/:id', async (req, res) => {
const { headers } = req;
let result;
try {
result = await axios({ method:'get', url: '/some-url', headers });
} catch(error) {
res.status(500).send(new Error('myError');
}
res.send({ result });
});
This does NOT work:
router.put('/:id', async (req, res) => {
const { headers } = req;
let result;
let finalResult;
try {
result = await axios({ method:'get', url: '/some-url', headers });
} catch(error) {
res.status(500).send(new Error('myError');
}
// logic based on the result of the above GET determines what the value of `finalResult`
finalResult = { some: 'data' };
res.send({ finalResult });
});
Even though axios({ method:'get', url: '/some-url' }) is the exact same in both routes, it works in one and not the other.
The router.put() route always hangs for a long time and eventually Node outputs:
Error: socket hang up, code: 'ECONNRESET', etc...
Appreciate any help, I've spent over a day scratching my head over this.
No there's no such thing in express. Try hitting the GET request from postman or curl and see if response is coming. The root cause could be an invalid get request you're trying to make or that server on which you are making GET request could be down. You can run following to validate
app.put('/',async (req, res) => {
let response = await axios.get('https://google.co.in');
console.log(response.data);
res.send({"works": "hello"});
});
Root cause of my problem:
The http Headers had a key of Content-Length that prevented GET calls to resolve correctly.
Since these api calls occurred within a router.put() callback, the Headers had a Content-Length pointing to the size of the payload "body" that was being PUT to begin with.
Solution:
Remove that Content-Length field from my Headers when doing GETs inside router.put(), such that the GET has all the other Headers data except for Content-Length
Unfortunately, NodeJS just threw that Error: socket hang up message that was not very descriptive of the underlying problem.

How to see axios error response JSON in React

I have a form in my react which allows users fill out their info and then sends a Post requests to create a new user in my database once submitted. I am using axios to make the http call with a node backend. The post request works on the backend, but I am now trying to handle errors on the front end (i.e. if a user enters an invalid email, the backend catches this and sends an error status back, and I want to display a message to the user saying they need to enter a valid email, etc).
I have the following code on my backend to handle the request:
const { check, validationResult } = require('express-validator/check');
studentRoutes.route('/add').post([
check('email').isEmail(), check('class_year').isInt({min: 2014, max: 2022})],
function (req, res) {
//make sure input is valid
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
.
.
.
//post call succesful
res.status(200).send("Student successfully Added to database");
});
On the front end, I make the http call as follows:
app.post('student/add', obj)
.then(res => console.log(res.data))
.catch(err => console.log(err));
where app is axios.
When I try this with correct data (i.e. should not return error), the message "Student successfully added to database" prints to the console as expected.
When I try this with a bad email (i.e. should return error), all that is printed to my console is:
(X) POST http://localhost:4000/student/add 422 (Unprocessable Entity)
Error: Request failed with status code 422
at createError (createError.js:17)
at settle (settle.js:19)
at XMLHttpRequest.handleLoad (xhr.js:78)
Where the first POST error is caught by my browser and the second part starting "Error: ..." is printed to the console.
When I try to access the error (err.errors or similar) it returns undefined. How can I access the status code and the body of the error sent?
Note: I have also tried replacing the line return res.status(422).json({ errors: errors.array() }); with return res.status(422).send({ errors: errors.array() }); but that does not help and the results are the same.
You should be able to access like this:
catch (err) {
console.error(err.response.data.errors);
}
Try:
error.message
Or depending on the backend config:
error.response

Resources