unable to access 200 code status in angular server response - javascript

Goal: If the server response with 200 code, I want to perform some changes on the record locally.
issue: I am not able to access the response code or the 'message' attribute
this is how the server response from this http call::
// MongooseModelSchema: this is the model that uses moongose
MongooseModelSchema.updateOne({ _id: req.params.id, creator: req.userData.userId }, channel)
.then(result => {
if (result.n > 0) {
res.status(200).json({ message: "Update successful!" }); // this is what I want to capture
} else {
res.status(401).json({ message: "Not authorized!" });
}
})
.catch(error => {
console.log(error);
res.status(500).json({
message: "Couldn't udpate channel!"
});
});
I am able to hit the API no problem
I have the following http snip in my angular code::
this.http
.put(BACKEND_URL+'setState/' + id, channelData)
.subscribe(response => {
console.log('response',response);
console.log('check if response has Update successful!: ',JSON.stringify(response).search('Update successful!'));
console.log('response.message',response.message);
this.router.navigate(["/editChannel", id]);
})
this is the console.log image:
issue image: as you can see, i dont have access to the return code. I also cant access the 'message' property UNTIL i run the code, then it works.... super weird.
How do I check for the 200 code?

That makes sense. Message object is not typed, so compiler is telling you that message doesn't exist on response. Instead what you should do is the following:
myresponse.ts:
interface MyResponse {
message: string
}
this.http
.put<MyResponse>(BACKEND_URL+'setState/' + id, channelData)
.subscribe(response => {
console.log('response',response);
console.log('check if response has Update successful!: ',JSON.stringify(response).search('Update successful!'));
console.log('response.message',response.message);
this.router.navigate(["/editChannel", id]);
})
now angular will grab the response and map it to the MyResponse interface giving you ability to access the message property. Alternatively you could keep it as any or unknown not sure what the type on response by default is, but if its any just do response['message']
Hope that helps.

Related

FormData sends undefined file to backend although the value has been assigned?

this might seem like a trivial question, but I'm truly don't know what is wrong with my code.
So, I've made this function that make a FormData, append it with name and value then sends it to the backend api:
const addGroup = () => {
const token = Cookies.get("X-API-KEY");
const formData = new FormData();
formData.append("firstlead", "Is Me");
formData.append("secondlead", "Is You");
formData.append("name", "Our Group");
axios
.post(
`http://localhost:7000/api/v1/groups`,formData,
{
headers: { authorization: token },
}
)
.then(() => {
notify();
});
};
The backend api code is:
// API POST DATA GROUP (admin)
router.post('/',authAdminMiddleware, async (req, res) => {
const {
firstlead,
secondlead,
name
} = req.body;
try {
console.log(firstlead)
console.log(secondlead)
console.log(name)
} catch (error) {
console.log(error);
return res.status(500).json({code:500,status:false,message:'Server Error'});
}
})
I don't know why, but the backend console log said that all of my variables (firstlead, secondlead, and name) are undefined despite it's clearly has been assigned a value. I've tried using Postman, and it actually works, so my guess is there is something wrong with my append code on the frontend, but again, I don't know what it is. Any help will be appreciated!
Below is the console.log from the backend, it receive undefined despite the value of firstlead, secondlead, and name has been declared on the addGroup function.
Undefined from backend

How to get message property of an error returned from an express server

I'm returning an error response from express like below.
router.post("/", authCheck, authCheckAdmin, (req, res, next) => {
const burger = new Burger({
_id: mongoose.Types.ObjectId(),
...req.body
});
console.log(burger);
Burger.find({ name: req.body.name })
.exec()
.then(result => {
if (!result) {
burger
.save()
.then(result => {
res.status(201).json({
message: "Burger Successully Created",
burger: result
});
})
.catch(error => {
res.status(500).json(new Error('Something went wrong when saving the burger')); // <------
});
} else {
res.status(500).json(new Error('Burger already exist'));
}
});
});
This is the React code
export const addBurger = burgerData => (dispatch, getState) => {
const currentState = getState();
axios
.post("/burgers", burgerData, {
headers: {
Authorization: `Bearer ${currentState.auth.token}`
}
})
.then(response => {
console.log(response);
})
.catch(error => {
console.error(error.message); <-------- Here
});
};
Below is the console preview
How can I get the message that I have passed inside express? I want to get "Burger already exist" as the error message. Is there another way to do this? Thanks
Server side fix
res.status(500).send({ error: 'Something failed!' })
According to me, error is not defined in the last else of your Burger.find method which is causing this error. This type of error's are mostly server side errors. Hope this work for you.
res.status(500).json(new Error('Burger already exiist')); // <------
if you would look at response in dev tools, you see that in this case payload is empty object. So you need directly tell the server what you need to send back. Try this if you already waiting for message key in react part:
res.status(500).json({message: 'Burger already exist'});

How to show a json object returned from the server

How can I get the JSON object that my backend is sending in my frontend code when the HTTP status is not 200?
When my backend is sending a 200-response I'm able to show the returned JSON data by doing this:
backend
res.status(200).json({status: 'Information found'})
frontend
.then(data => console.log(data.status)) // Information found
However when I'm trying to do the same with a 400 or 404 status I can't get the returned JSON.
backend
res.status(404).json({error: 'No information found'});
frontend
.catch(error => console.log('Error from backend', error))
result
I first tried error.error but that's undefined.
What is the difference with the 200-status return and how can I get the message that I'm sending from the backend in my frontend?
EDIT
Frontend
axios.post('https://firebaselink.net/getTestData', { id: orderNumber })
.then(data => console.log(data.status))
.catch(error => console.error(error))
Backend
export const getTestData = functions.https.onRequest((req, res) => {
cors(req, res, () => {
const id = req.body.id;
admin.database().ref(`data/${id}`).once('value')
.then(snapshot => {
if(snapshot) res.status(200).json({status: "Information found"})
else res.status(404).json({error: "Information not found"})
}).catch(error => res.status(500).json({error: 'Internal error}))
})
})
Q: I tried error.error but that's undefined. How do I print my error?
A: Javascript is untyped, meaning an object can be anything. The best solution here would be to do a console.log(JSON.stringify(error, null, 2) to see what property it has and then access to print out the message.
An error object would typically have the message property.
References:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error

How can axios get the status code in .catch()?

In the Axios document:
axios.get('/user/12345')
.catch(function (error) {
if (error.response) {
// The request was made and the server responded with a status code
// that falls out of the range of 2xx
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// The request was made but no response was received
// `error.request` is an instance of XMLHttpRequest in the browser and an instance of
// http.ClientRequest in node.js
console.log(error.request);
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error', error.message);
}
console.log(error.config);
});
we know we can catch the error in the .catch() method.
But when I use the Django-Rest-Framework as the backend API provider. it only provide the data, there is no status in it:
You see the error:
{username: ["A user with that username already exists."]}
but in the browser, we can know the status code:
Before asking this question, I have read How can I get the status code from an http error in Axios?
this post.
But the post seems different with mine.
EDIT-1
In my Django-Rest-Framework project:
the view:
class UserCreateAPIView(CreateAPIView):
serializer_class = UserCreateSerializer
permission_classes = [AllowAny]
queryset = User.objects.all()
the serializer:
class UserCreateSerializer(ModelSerializer):
"""
user register
"""
class Meta:
model = User
fields = [
'username',
'wechat_num',
'password',
]
extra_kwargs = {
"password":{"write_only":True}
}
def create(self, validated_data):
username=validated_data.pop('username')
wechat_num = validated_data.pop('wechat_num')
password=validated_data.pop('password')
user_obj = User(
username=username,
wechat_num=wechat_num,
)
user_obj.set_password(password)
user_obj.save()
group=getOrCreateGroupByName(USER_GROUP_CHOICES.User)
user_obj.groups.add(group)
return validated_data
I find in the interceptors configuration:
Axios.interceptors.response.use(
res => {
return res;
},
error => {
return Promise.reject(error.response.data)
}
);
I was return the error.response.data directly, I could configure it to error.response, or error.
if I configure the error.response, then in the .catch() I can console like bellow:
console.log(response.data);
console.log(response.status);
console.log(response.headers);

feathersjs: How do I pass un-opinionated errors back to client

Seems like error messages are wrapped in text. Say in a model validation I just want to send "exists" to the client if a record already exists.
One the server maybe I do something like:
validate: {
isEmail: true,
isUnique: function (email, done) {
console.log("checking to see if %s exists", email);
user.findOne({ where: { email: email }})
.then(function (user) {
done(new Error("exists"));
},function(err) {
console.error(err);
done(new Error('ERROR: see server log for details'));
}
);
}
}
On the client maybe I do:
feathers.service('users').create({
email: email,
password: password
})
.then(function() {
console.log("created");
})
.catch(function(error){
console.error('Error Creating User!');
console.log(error);
});
The error printed to console is:
"Error: Validation error: exists"
How to I just send the word "exists" without the extra text? Really I'd like to send back a custom object, but I can't seem to find any examples of doing this. The closest I've seen is this: https://docs.feathersjs.com/middleware/error-handling.html#featherserror-api
But I haven't figured out how to make something like this work in the validator.
Feathers does not change any error messages so the Validation error: prefix is probably added by Mongoose.
If you want to change the message or send an entirely new error object, as of feathers-hooks v1.6.0 you can use error hooks:
const errors = require('feathers-errors');
app.service('myservice').hooks({
error(hook) {
const { error } = hook;
if(error.message.indexOf('Validation error:') !== -1) {
hook.error = new errors.BadRequest('Something is wrong');
}
}
});
You can read more about error and application hooks here

Categories