angular 2 get call thorwing error, after status 200 - node.js

I am calling my get rest service like this,
makeGetCall(url: string): Observable<any> {
const headers = new Headers({'auth-code': 'auth-code',
'from':'app'});
return this.http.get(AdminConstants.BASE_URL + this.SEPARATOR + url,{
headers: headers
})
.map(this.extractData)
.catch(this.handleErrorObservable);
}
private extractData(res: Response) {
console.log('extract data');
console.log(res);
const body = res.json();
return body || {};
}
private handleErrorObservable(error: Response | any) {
console.log('error in service');
console.log(error.message);
return Observable.throw(error.message || error);
}
and My rest service is:
console.log('inside get all user');
ApiUser.find().then(users => {
console.log('length : '+users.length)
res.status(200).send(users);
}, error => {
res.send(500).send(error);
})
I am using MEAN stack for my application.
Here is my problem, when I am calling my rest service from postman its working.Even in the chrome/mozilla console I can see my response as expected.response header
But from my angular 2 application my handleErrorObservable method is called and that too with an error without proper message.
I just installed ssl certificates on my server, before ssl this was working inside my application.
Also to add post requests are working.
I don't know what I am missing.
Please help.
Thanks in advance.

Thanks to #kirkLarkin
I just added res.set('Access-Control-Allow-Origin','*'); in my rest service and it worked.

Related

Why am I getting a "400: Bad Request" but the request successfully posts to my DB

I am not sure what is happening. I had all the same code setup in dev using localhost and everything was working fine. I hosted my app to Vercel and my API to heroku and from what I can tell the API is working perfectly. The issue now is when I make a post request I get a 400 Bad Request error in the browser but it still makes the request and posts to my DB I have setup. Any help can be appreciated. I built this application in a MERN stack with NEXT.js
Here is my client side Post request
const postSubmit = async e => {
e.preventDefault();
try {
const { data } = await axios.post('/create-post', { content, image });
if(data.error) {
toast.error(data.error);
} else {
setPage(1);
newsFeed();
toast.success("Post created");
setContent('');
setImage({});
// socket.emit('new-post', data);
}
} catch(e) {
console.log(e);
}
}
Here is my server side handling of the post request
export const createPost = async (req, res) => {
const { content, image } = req.body;
if(!content.length) {
return res.json({
error: 'Content is required'
})
}
try {
const post = new Post({ content, image, postedBy: req.user._id });
await post.save();
const postWithUser = await Post.findById(post._id).populate('postedBy', '-password -secret');
res.json(postWithUser);
} catch (e) {
console.log(e);
res.sendStatus(400);
}
};
And here is what the browser is telling me
Chrome Browser Info
This is most likely caused by a typo on the MongoDB connection string (URI), similar to this answer.
In the linked answer, the typo was the semi-colon in &w=majority;. In your case, the value is somehow majorityDATABASE=, so double-check your MongoDB connection string and try to remove the extra DATABASE= in the write concern parameter.
It's likely that the await Post.findById() call is not finding a result which could be throwing an error when you try to call res.json(postWihUser). That would then cause an error when postWithUser is not defined.
What is logged to the server's terminal when an error occurs? That should help you identify the problem.

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client NodeJS with Firebase

Description
Everytime I include response.send(snapshot.val()); this error is occurred and the NodeJS server crashed. I am using Postman to test the API endpoint with Header it is worked okay.
Output
On terminal 401 Unauthorized
[2020-11-05T13:23:24.421Z] #firebase/database: FIREBASE WARNING: Exception was thrown by user callback. Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
NodeJS
const getsRoute = require('./routes/gets');
app.use('/api/v1', getsRoute);
//on other file
const auth = require('../middleware/auth');
router.get('/products', auth, (req, res) => {
initialPage.getBusinesses(res);
});
Code to Produce error
const initialPage = {
getBusinesses(response) {
ref.orderByKey()
.limitToLast(20)
.on('value', function(snapshot){
response.json(snapshot.val());
return snapshot.val();
})
}
}
Client side using React Native
searchApi = async() => {
const response = await axios.get('http://33c75838823c90.ngrok.io/api/v1/products',{
headers: {
"Content-Type": "application/json",
"Accept": "application/json",
"x-auth-token":"jgiiHDgfdeizI1NiIJ9.eyJfaWQiOiI1ZmEwMWMzZmM4YjIwYjBjZDQyMmJkNzUiLCJpYXQiOjE2MDQ0MTAwMDZ0KwFAgVtsJUQw"
}
}
).catch((error) => {
console.log("ERROR FROM AXIOS:", error)
});
console.log("RESPONSE DATA: %%%%%%%", response.data)
this.setState({results: [response.data]});
}
I have checked so many documents and questions forum but no one get exactly the solution suit for general problem.
The problem is here:
getBusinesses(response) {
ref.orderByKey()
.limitToLast(20)
.on('value', function(snapshot){
response.json(snapshot.val());
return snapshot.val();
})
}
Since you're using on(...), your callback will be called:
As soon as the data is loaded,
After that, any time the data changes.
The first one is working as intended, but if the data ever changes this means you're trying to send another response, which is what's causing the error.
To solve this, use once instead of on:
getBusinesses(response) {
ref.orderByKey()
.limitToLast(20)
.once('value', function(snapshot){
response.json(snapshot.val());
return snapshot.val();
})
}

How can I capture HttpErrorResponse status and display it in angular component

I have an angular project back end with node.js, how can I call and get httpErrorResponse status or headers to display in my components page when my server is down or not responding.
here is my component function code:
UpdateData(){
this.newServices.updateNews(result, result.id).subscribe(
(res)=>{
console.log(res)
}),
(error)=>{
console.log(error)
}
}
my service.ts function:
updateNews(data, id) {
try {
return this.http.post(this.baseurl + "/news/update/" + id, data)
} catch (err) {
this.handleError(err);
}
}
how can I check in my component the http responses so that I can display messages on the browser
Generally its not advisable to show the error message to the user that returned from server. For example the error may be: Cant reach the xx.xx.xx due to CORS policy. So if u show this the user cant understand whats happening. So its advisable to use a toaster Service to show error to user.
https://www.npmjs.com/package/ngx-toastr
getPlayersList() {
this.playerService.getPlayersList().subscribe((res: any) => {
this.playersData = res.data;
}, err => {
this.toasterService.showFailure('Sorry something went wrong');
})
}
In some scenarios if u want to show the error thats coming from api like 500 response u can do in this way
getPlayersList() {
this.playerService.getPlayersList().subscribe((res: any) => {
this.playersData = res.data;
}, err => {
this.toasterService.showFailure(err.err.message);
})
}
Try this:
In your service:
updateNews(data, id) {
return this.http.post(this.baseurl + "/news/update/" + id, data)
}
In your function:
this.newServices.updateNews(result, result.id).subscribe(
(res)=>{
console.log(res)
}),
(error)=>{
console.log(error)
}

How to deal with backend dynamically allocated ports on react.js side using axios?

This morning I deployed a MERN stack login app in heroku successfully. But, when I tried to login
GET http://localhost:5000/user/login/email/password net::ERR_CONNECTION_REFUSED
in the console.
I understood that that the error is because I am making get request in axios using
axios.get("http://localhost:5000/user/login/" + this.state.email + "/" + this.state.password).then((res) => {
if (res.status === 200) {
this.setState({ status: res.status, name: res.data.name });
console.log(res.data);
}
else
throw new Error(res.status);
}).catch((err) => {
this.setState({ isInvalid: true });
})
But, the port is being dynamically allocated on the server side.
const port = process.env.PORT||5000;
app.listen(port, () => {
console.log("Server started on port:" + port);
});
Tried allocating only hardcoded value to the port. Still no luck
There are lots of mistakes in your code. You have deployed your app but your URL is still localhost which is not Heroku URL. First of all you need to setup env variables for your application like this.
You can put this in some constant file from where you get your end point. Don't write END POINTS directly in the ajax calls. Use constant and create a single file for from where you do all the ajax calls of the application.
You can set the env for both frontend and backend and this is how you should work. The development env should be separate from production one.
if (process.env.NODE_ENV === "development") {
API = "http://localhost:8000";
} else if (process.env.NODE_ENV === "production") {
API = "https://be-prepared-app-bk.herokuapp.com";
}
Don't use GET for the login and sending email and password in parameters. You should use POST and send all the data in body.
Here's how you single ajax file should look alike:
import { API_HOST } from "./constants";
import * as auth from "../services/Session";
const GlobalAPISvc = (endPoint, method, data) => {
const token = auth.getItem("token");
const uuid = auth.getItem("uuid");
return new Promise((resolve, reject) => {
fetch(`${API_HOST}${endPoint}`, {
method: method,
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
"x-authentication": token,
uuid: uuid
}
})
.then(res => {
return res.json();
})
.then(json => {
resolve(json);
})
.catch(error => {
reject(error);
});
}).catch(error => {
return error;
});
};
export default GlobalAPISvc;
I have created an application in MERN which I made public on GitHub. Feel free to take help from that. Repository Link
Firstly, I would suggest you, not to use get request method for login.
Secondly, if you've deployed your backend code then use dynamic url provided by heroku for login request.
e.g. if your url is xyz.heroku.com then axios.get('xyz.heroku.com/user/login/'+email+'/'+password);
as now you don't need to hard-code the port or use localhost.

Not able to call a backend function 404 not found

I am running a Express application with Node in the backend. I have 2 functions in a component in NodeJS which I am trying to access from my service. The link for both are the same in the service. It is able to connect one of the functions from the service.
However, it is showing 404 not found for accessing the second function in the same component. It is strange that the 2 functions from the same service is are giving 2 different responses (1 success and 1 failure).
Has anyone faced any such issue and if so how can it be rectified?
Some code for reference :
component1.component.ts
getallprojectcat()
{
this.authenticationService.getprojectcat()
.pipe(first())
.subscribe(
data => {
this.data = data;
},
error => {
this.loading = false;
});
}
}
component2.component.ts
showprojects(moid)
{
this.authenticationService.getprojectslist(moid)
.pipe(first())
.subscribe(
data => {
this.silver = data;
},
error => {
console.log('some error');
this.alertService.error(error);
this.loading = false;
});
}
the .service file
getprojectcat()
{
return this.http.get<any>(this.studenturl+'/getprojectcata/')
.pipe(map(allprojectcat => {
console.log(JSON.stringify(allprojectcat));
return allprojectcat;
}));
}
getprojectslist(moid)
{
return this.http.get(this.studenturl+'/getprojects/'+moid)
.pipe(map(projectslist => {
console.log("Projects List:"+JSON.stringify(projectslist));
return projectslist;
})).catch(this.handleError);
}
Backend .js file
exports.getprojectcata = function(req, res){
console.log("First Function");
};
exports.getprojects = function(req, res){
console.log("Second Function");
};
The function getprojectcata is working in the first component. However, it shows an 404 not found on the getprojects function in the second component. I have checked the following things -
Routing does not seem to be the problem as it is moving to the next component without any issues.
We have also tried calling the getprojectscata through the same service in component and it worked.
For sencond function use .post in service and backend route also.
As GET requests is only used to request data. And you are passing moid in http.get which gives 404.
In post you can send moid data in params and in backend fetch data as req.params.
I hope it wil help you .
Share your code for better understanding.

Resources