Angular2 http returns empty response? - http

I have a backend API, which as shown in this POSTMAN screenshot is working.
Here is my service:
getComments(line: string, department: string, startTime?: number, endTime?: number): Observable<Array<IComments>> {
let headers = new Headers(
{
'Content-Type': 'application/x-www-form-urlencoded',
'line': line,
'cell': department,
'start': new Date(),
'end': ago(24, "hours")
});
let options = new RequestOptions({ headers: headers });
return this.http.get('api/data/comments', options)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || {};
}
and this is what my component contains:
this.dataService.getComments('604', 'powders').forEach(result => {
console.log('Res: ' + JSON.stringify(result));
that.comments = result;
});
However, all I get in the console is:
Res: {}
Why is the data not being returned, as it is in postman?
Update:
and if I console.log(body) in extractData, then I get:
Object {result: "COMMENTS604"}

In extractData you are returning body.data, but since the property is named result, I think you meant to return body.result

Related

Http post in angular 7 returns invalid response

I am using http post for one of my angular application for login.I have checked the url with the params in postman which gives me the output.But when i try to use the same in the application i am getting the error as invalid login all the time.
I would like to know whether the way i pass the params are correct or not?
const formData = `username=${username}&password=${password}`;
const options = { headers: new Headers({ 'Content-Type': 'application/x-www-form-urlencoded' }) };
return this.http.post<any>(`${this.baseUrl}?action=login&`, formData, options)
.pipe(map(response => {
console.log('user is', response);
if (response && response.session && response.session.id) {
localStorage.setItem('currentUser', JSON.stringify(response));
this.currentUserSubject.next(response);
}
return response;
}));
The error i am getting is
user is {error: "Incorrect Login."}
You can try like this instead of formData
const data = new HttpParams()
.set('username', username)
.set('password', password);
return this.http.post<any>(`${this.baseUrl}?action=login&`, data)
.pipe(map(response => {
if (response.status === 'success') {
localStorage.setItem('currentUser', JSON.stringify(response));
this.currentUserSubject.next(response);
}
return response;
}));

JS Function returns the value before promise resolves

I want to block the function from returning value before promise resolves. And, pushheaders returns an promise obj instead of just value,
i just want pushheaders to return token which fetched from the firebase
import firebase from 'firebase';
let promise1 = new Promise((resolve, reject) => {
firebase.auth().currentUser.getIdToken().then(token => {
resolve(token);
}).catch(err => {
reject(err)
});
});
export function pushHeaders (ct) {
let b = await promise1.then(data => data);
let headerz = {
headers: {
Authorization: 'Bearer ' + b,
}
}
ct ? (headerz.headers['Content-Type'] = ct) : null;
return headerz;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.min.js"></script>
There is no way to synchronize promises so with await your function needs to be async:
export async function pushHeaders(ct) {
const token = await promise1; // no need for a noop
const headers = {
headers: {
Authorization: `Bearer ${token}`,
...(ct ? { 'Content-Type': ct } : {}), // ECMAScript2018
},
};
return headers;
}
This also means that it returns a promise and not headers directly. To get the actual result you either need to use then or use asycn/await again on the callee.
I see you are using await, which is a typescript keyword, which is only allowed when you mark your function with Async, try that
export async function pushHeaders (ct) {

Angular2 response not mapping to TypeScript object

I'm struggling to figure out why the response I get from my API isn't mapping to an object that I have in typescript.
Here's the function in my service that calls the API:
register(user: IUser): Observable<IUser> {
var headers = new Headers();
headers.append('Content-Type', 'application/json');
var options = new RequestOptions({
headers: headers,
url: this._registerUrl,
body: JSON.stringify(user)
});
return this._http.post(this._registerUrl, { user }, options)
.map((res: Response) => res.json() as IUser)
.catch(this.handleError);
}
This is the function that calls the service:
register(): void {
let user: IUser = {
email: this.email,
username: this.username,
password: this.password
}
this._userService.register(user)
.subscribe(result => {
debugger;
if(result.errorCode > 0)
this.handleError(result.errorCode);
else {
localStorage.setItem('userId', result.userId.toString());
localStorage.setItem('username', result.username.toString());
localStorage.setItem('email', result.email.toString());
}
});
}
The object that I am returning from the API matches the object that I have in the frontend. It is returning the data and I can see it in the body of my response. All of the data is right, but it's in the body and is not turning it into an IUser object.
Does anybody have any ideas? Thanks.
EDIT
This is what the response object looks like when it comes back from the service.

Ionic 2 - Get token from Storage value and set Header before HTTP Request

I am using the ionic/storage package to store the api_token for users after they logged in so I can use the unique token to interact with an API.
The problem I am facing is that I need to get the value via storage.get which returns a promise and results in the headers I want to set not being set in time.
I need to return an instance of RequestOptions but can't figure out how to add the header I retrieve when it comes from a promise. Adding a header synchronous with localStorage is working fine when testing so the issue must be the asynch execution.
createAuthorizationHeader(headers: Headers) {
// this does add the header in time
localStorage.setItem('api_token', 'some token');
headers.append('Authorization', 'Bearer ' + localStorage.getItem('api_token'));
// this does not add the header in time
return this.storage.get('api_token').then((value) => {
headers.append('Authorization', 'Bearer ' + value);
});
}
getHeaders(path): RequestOptions {
let headers = new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json'
});
if(!this.isGuestRoute(path)) {
this.createAuthorizationHeader(headers);
}
return new RequestOptions({ headers: headers });
}
get(path: string) {
return this._http.get(this.actionUrl + path, this.getHeaders(path))
.map(res => res.json())
.catch(this.handleError);
}
Edit: Working code now looks like this
getApiToken(): Observable<Headers> {
return Observable.fromPromise(this.storage.get('api_token'));
}
getHeaders(): Headers {
return new Headers({
'Accept': 'application/json',
'Content-Type': 'application/json'
});
}
get(path: string) {
let headers: Headers = this.getHeaders();
if(!this.isGuestRoute(path)) {
return this.getApiToken().flatMap(data => {
headers.append('Authorization', 'Bearer' + data);
return this._http.get(this.actionUrl + path, { headers : headers })
.map(res => res.json())
.catch(this.handleError);
});
}
return this._http.get(this.actionUrl + path, { headers : headers })
.map(res => res.json())
.catch(this.handleError);
}
Check out my similar problem Angular2 - Use value of Observable returning method in another Observable
If you convert the Promise to a Observable you will be able to use the rxjs flatMap function.
Let me show you what your would somewhat look like then
getApiToken(): Observable<Headers> {
return Observable.fromPromise(this.storage.get('api_token'));
//OR return Observalbe.of(this.storage.get('api_token'));
}
getHeaders(): Headers {
//create all headers here except the 'api_token'
.....
}
get(path: string): Observable<any> {
let headers: Headers = this.getHeaders();
return this.getApiToken().flatMap(data => {
headers.append('Authorization', 'Bearer'+data);
return this.http.get(this.actionUrl + path, headers)
.map(res => res.json())
.catch(this.handleError);
});
}
OR (Just learned about this so not sure if it will work)
createAuthorizationHeader(headers: Headers) {
// this does add the header in time
localStorage.setItem('api_token', 'some token');
headers.append('Authorization', 'Bearer ' + localStorage.getItem('api_token'));
// this does not add the header in time
let api_token = await this.storage.get('api_token');
headers.append('Authorization', 'Bearer ' + api_token);
}
I would suggest looking at Interceptors: https://angular.io/guide/http (serach for the section named "Setting new headers"). I tried using BaseRequestOptions but that still causes an async problem.
Regadring Ivaro18 answer, of setting the headers as the token is received and saved in storage, won't that break when the user returns to an app/page after killing the app/ closing browser? The header are set in memory, so it won't be persistent.

Calling functions before subscribing

I have a http call to a remote server using the angular2/http and thats all working awesomely and such. But I'm having trouble with using the observables that it returns.
When I do my http calls, I'm going through 3 different components.
(for ease here ill just make the calls 3 different methods instead as it works out the same)
What I want to know if its possible to do, is use subscribe twice on the same observable or if there is a way that I can call some functions so I can add logging in the request rather than needing to add it at every location that I make a http call.
request(type: RequestMethod, url: string, data: any) {
let params: URLSearchParams = new URLSearchParams();
let req: RequestOptions;
let headers = new Headers();
for (let key in data) {
params.set(key, data[key]);
}
if (type === 0) {
req = new RequestOptions({
method: type,
search: params
});
} else {
headers.append('Content-Type', 'application/x-www-form-urlencoded');
req = new RequestOptions({
method: type,
body: params.toString(),
headers: headers
});
}
console.log('Http Request: ' + url);
console.log(req);
return this.http.request(this.testUrl + url, req)
.map((res: Response) => res.json());
// .subscribe(
// data => {
// console.log('Data Return for ' + url);
// console.log(data.data);
// // return data; //i removed this subscribe so i can
// }, //pass the map back through and
// err => { //use the subscribe later in the initial call
// this.logError(url, err);
// },
// () => {
// if (afterSuccess) {
// afterSuccess();
// }
// console.log('Completed '+ url);
// }
// );
}
logError(url: string, err: any) {
console.log('Error in call: ' + url);
console.log(err);
}
get(url: string, data: any) {
return this.request(RequestMethod.Get, url, data);
}
post(url: string, data: any) {
return this.request(RequestMethod.Post, url, data);
}
emailExists(email_address: string, user_type?: string) {
let data: any = {};
data.email_address = email_address;
data.service_provider_id = this.service_provider_id;
if (user_type) {
data.user_type = user_type;
}
return this.get('emails/email-address/exists', data);
}
ngOnInit() {
this.emailExists('an.email#gmail.com').subscribe(data => {
this.email = data.data;
console.log('in Signin');
console.log(this.email);
}, err => {
console.log(err);
}, () => {
});
}
In the request method I want to be able to call a console.log to print out the url that was used and print the data received from the server or any errors.
I know I could add it to the success and error portions of the subscribe in the emailExists() call in ngOnInit() but that would mean I would need to put those in every single call throughout the app.
Thanks in advance for your help and time.
You could leverage the do, catch and finally operators of observables to do that.
Here is a sample:
return this.http.request(this.tpayUrl + url, req)
.map((res: Response) => res.json())
.do(data => {
console.log('Data Return for ' + url);
console.log(data.data);
})
.catch(err => {
this.logError(url, err);
return Observable.throw(err);
})
.finally(() => {
if (afterSuccess) {
afterSuccess();
}
console.log('Completed '+ url);
});

Resources