Cannot make a simple http GET call in Angular2 - javascript

I am trying to make a simple http GET request from my Angular2 app:
this.http.get("https://mybaseurl.com/hello")
.map(res => res.json())
.subscribe(
function(response) { console.log("Success Response" + response)},
function(error) { console.log("Error happened" + error)},
function() { console.log("the subscription is completed")}
);
The Node.js server is configured this way:
app.get('/hello', function(req, res) {
res.send("hellow world");
});
When I make the call I keep getting this error:
caused by: unable to parse url 'https://mybaseurl.com/hello'; original error: Cannot read property 'split' of undefined
at InMemoryBackendService.parseUrl (in-memory-backend.service.ts:518)
at InMemoryBackendService.handleRequest (in-memory-backend.service.ts:279)
at InMemoryBackendService.createConnection (in-memory-backend.service.ts:240)
Any idea what am I doing wrong?
edit: pasting the entire class code:
import {Component} from '#angular/core';
import {Auth} from './auth.service';
import {AuthHttp} from 'angular2-jwt';
import {Http} from '#angular/http';
import 'rxjs/add/operator/map';
#Component({
selector: 'ping',
templateUrl: 'app/ping.template.html'
})
export class ApiService {
API_URL: string = 'https://myapp.herokuapp.com';
message: string;
constructor(private auth: Auth, private http: Http, private authHttp: AuthHttp) {}
public ping() {
this.http.get(`${this.API_URL}/hello`)
.map(res => res.json())
.subscribe((response) => {
console.log("Success Response" + response)
},
(error) => { console.log("Error happened" + error)},
() => { console.log("the subscription is completed")}
);
}
}
=====>
This looks like a HUGE bug in Angular2 - all http requests return null, or an error message describing it is not in the required pattern.
I someone has a working demo of HTTP GET I would love to see

It looks like using InMemoryWebApiModule.forRoot(InMemoryDataService) in #NgModule simultaneously with Http.get causes uncovered urls to return null and error.
Setting it this way worked for me:
InMemoryWebApiModule.forRoot(InMemoryDataService, {passThruUnknownUrl: true})

Maybe it is beacause of your answer from server - you send string to client, but in map function you try to call res.json(). Can you comment map function call?

Check by using arrow function for success and error as below :
this.http.get("https://mybaseurl.com/hello")
.map(res => res.json())
.subscribe((response) => { console.log("Success Response" + response)},
(error) => { console.log("Error happened" + error)},
() => { console.log("the subscription is completed")}
);

Related

subscribing in Angular

I am completely new to Angular and I've created a project using SpringBoot 2.0.5.RELEASE, Angular 5 and spring data to build an end to end single page java web application. I use spring boot 1.5 to expose REST APIs and angular5 with routing to build the client that will consume the APIs exposed by the server.
I've defined this component:
import { Component } from '#angular/core';
import { Router } from '#angular/router';
import { User } from '../models/user.model';
import { UserService } from './user.service';
#Component({
templateUrl: './add-user.component.html'
})
export class AddUserComponent {
user: User = new User();
constructor(private router: Router, private userService: UserService) {
}
createUser(): void {
alert ('lala');
this.userService.createUser(this.user)
.subscribe( data => {
alert('User created successfully.');
});
}
}
in the page I can see the alert lala, but not 'User created successfully.' but I have no idea why
The link address when I create a user is this is this one http://localhost:4200/api/users
This is my proxy.config.json file:
{
"/api/*": {
"target": "http://localhost:8080/user-portal",
"secure": false
}
}
and from curl is fine :
curl -X POST -H "Content-Type: application/json" "http://localhost:8080/user-portal/api/users"
and user.service.ts:
import {Injectable} from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { User } from '../models/user.model';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
#Injectable()
export class UserService {
constructor(private http: HttpClient) {}
private userUrl = '/api/users';
public getUsers() {
return this.http.get<User[]>(this.userUrl);
}
public deleteUser(user) {
return this.http.delete(this.userUrl + '/'+ user.id);
}
public createUser(user) {
return this.http.post<User>(this.userUrl, user);
}
}
Firstly, best not to use alert. Use console.log. Secondly, you are only handling success, you are not handling failure. Do this:
createUser(): void {
console.log('lala');
this.userService.createUser(this.user)
.subscribe(data => {
console.log('User created successfully', data);
},
err => {
console.log('There was an error', err);
},
() => {
console.log('I have completed now and nothing will ever be emitted from this Observable again');
});
}
The error handler will be executed if the HTTP response is not a success response, viz if the status code of the response is not in the 2xx range.
Check your browser network tab also to see if the HTTP request is failing.
You prob also want to debug this:
public createUser(user) {
console.log('userUrl', this.userUrl)
console.log('user', user)
return this.http.post<User>(this.userUrl, user);
}
To make sure all is as expected.
In Chrome hit F12 to open the dev tools and go to the network tab. Make sure that a request is being made to the end point and that it is not throwing and error.

Angular: Make Post Request From ErrorHandler?

I am trying to send any errors, exceptions that Angular is catching to my server. I made my own class called GlobalErrorHandler that is extending ErrorHandler. Please check below
import { ErrorHandler, Injectable, Injector } from "#angular/core";
import {HttpHeaders, HttpClient} from "#angular/common/http";
import { TestServiceService } from "../_services/test-service.service";
#Injectable()
export class GlobalErrorHandler implements ErrorHandler {
constructor(
private injector: Injector,
private http: HttpClient,
private service: TestServiceService,
) {}
url = 'http://127.0.0.1:4000/post';
handleError(error) {
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json'})
};
try {
let msg = JSON.parse(error)
console.log('>>>>>>>>> message is ', msg)
this.http.post(this.url, msg, httpOptions);
}
catch (e) {
console.log('>>>>>>>>> err in catch is ', e)
}
}
}
I am able to console.error(error) whenever an error occurs, but I cannot make a post request to my server.
What am I missing in my code to make post request from ErrorHandler?
After changing the code to the following (replacing JSON.parse with JSON.stringify and catching the post errors successfully):
handleError(error) {
const httpOptions = {
headers: new HttpHeaders({'Content-Type': 'application/json'})
};
let subscription = this.http.post(this.url, JSON.stringify(error), httpOptions).subscribe(
(data => {console.log('>>>>>>> data is ', data));subscription.unsubscribe();},
error => {console.log('>>>>>>>> err', error);subscription.unsubscribe();}
)
}
The error was discovered to be on the serverside, but the code above should be useful to anyone trying to trasmit clientside errors(in Angular2+) to the server provided that the server has been implemented correctly.

Angular 2 JSONP injected script did not invoke callback error

I am running app on localhost://3000 with npm server
Services file:
import {Injectable} from "#angular/core";
import {Jsonp} from "#angular/http";
import 'rxjs/add/operator/map';
#Injectable()
export class futScoreService{
constructor(private _jsonp:Jsonp){}
getCompetitions(){
let queryString ='?callback=JSONP_CALLBACK';
return this._jsonp.get('http://api.football-data.org/v1/competitions/' + queryString,{method: 'Get'})
.map((res) => res.json());
}
}
Component file:
ngOnInit(){
this._futScoreService.getCompetitions().subscribe(
(comp)=>{
console.log(comp);
},
(err)=>{
console.log(err);
}
);
}
And I'm getting this error in console console-error
and on network tab I get object from API network-tab
Ok solution was making get request with http module and providing header with get request. Header part was main reason why it was failing.
let headers = new Headers({'X-Mashape-Key':'Ns0SkjyRRomshq3PgEnGoz2Zkc71p1CYnWajsnphGctvrGt46W'});
headers.append( 'Accept', 'application/json');
return this._http.get("http://api.football-data.org/v1/competitions/",{
headers: headers
})
.map((res) => res.json());
Angular is replacing JSONP_CALLBACK with
__ng_jsonp____req0_finished
but it should be
__ng_jsonp__.__req0.finished
Inspect your Network response. If you see __ng_jsonp____req0_finished({...json object...}) this is the problem.
Also, some services have different requirements for the callback query string parameter, which proves to be nasty because the error is exactly the same. I was using &callback=__ng_jsonp__.__req0.finished with MailChimp which produced the same error but the response had only a json object and no callback function. This is because MailChimp's spec is to use &c= instead of &callback=
When hardcoding the Jsonp callback (re: JSONP_CALLBACK issue) you need to account for the number of calls made, as Angular persists the state of each call. An example of what I'm doing for Mailchimp:
addEmailToList(email: string, listId: string, jsonpCalls: number, callback: any) {
const cbJsonp = '__ng_jsonp__.__req' + jsonpCalls + '.finished';
let url = [
'http://',
host,
'/subscribe',
'/post-json',
].join('');
let queryParams: URLSearchParams = new URLSearchParams();
queryParams.set('u', Config.MAILCHIMP_API_KEY);
queryParams.set('id', listId);
queryParams.set('EMAIL', email);
queryParams.set('c', cbJsonp); // non-standard; varies by service; usually 'callback'
...
}
this._InstUrl = "your url";
let params1 = new URLSearchParams();
//params.set('search', term); // the user's search value
//params.set('action', 'opensearch');
params1.set('format', 'json');
//params1.set('callback', "ng_jsonp.__req0.finished");
params1.set('callback', "JSONP_CALLBACK");
return this._jsonp
.get(this._InstUrl, { search: params1 })
.map(response => { debugger; this.Result = response.json().data })
.subscribe(
(data) => {
debugger
console.log(this.Result);
},
(error) => {
debugger
console.log(error);
});

Angular 2 HTTP GET to Node backend for list of file names in directory

I'm trying to use an Angular 2 HTTP GET request to simply connect with a Node/Express backend that responds with a list of the file names in a certain folder using the fs.readdir method.
I set up the Angular 2 request as a service:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable } from 'rxjs/Observable';
import './rxjs-operators';
#Injectable()
export class PhotoService {
constructor (private http: Http) {}
private photosUrl = '/api/photos'; // URL to web API
getPhotos() : Observable<string[]> {
return this.http.get(this.photosUrl)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError (error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
}
and then called this service from a component:
ngOnInit() {
this.photoService.getPhotos()
.subscribe(
photos => this.fileList = photos,
error => this.errorMessage = <any>error);
}
This is the Node backend (with Express set up as per conventions):
//Photo Service
app.get('/api/photos', function(req, res) {
fs.readdir('./uploads', function(error, files) {
if (error) {
throw error;
}
else {
res.end(files);
}
});
});
As seen, the HTTP request calls a GET method to http://localhost:3000/api/photos and the Node backend is supposed to receive that request and send back an array of strings that have the names of files in the 'uploads' folder.
However it does not seem to be working. I think I'm getting confused with the format in which the Node API sends the response and how that works with the Observable type that Angular uses in the service.
Your Angular 2 code looks good to me. But in your Node backend you should not send data with res.end() (see the documentation). Correct would be res.send(files); or in your case res.json(files); which will also set the right Content-Type header.

Invalid credentials error in Angularfire2 oauth login

I'm trying to login to my Ionic 2 app using Facebook native and Angularfire2 (2.0.0-beta.2), but even though I am successfully getting an access token, no matter how I try to pass it in to angularfire's auth.login function it still throws an invalid credentials error.
Here is my config:
firebaseAuthConfig({
provider: AuthProviders.Facebook,
method: AuthMethods.OAuthToken,
remember: "default",
scope: ["email"]
})
And here is my login function:
login() {
Facebook.login(["public_profile", "email", "user_friends"])
.then((success) => {
console.log("Facebook success: " + JSON.stringify(success));
this.af.auth.login(success.authResponse.accessToken, { provider: AuthProviders.Facebook })
.then((success) => {
console.log("Firebase success: " + JSON.stringify(success));
})
.catch((error) => {
console.log("Firebase failure: " + JSON.stringify(error));
});
})
.catch((error) => {
console.log("Facebook failure: " + JSON.stringify(error));
});
}
And here is the error I get in my console.log:
Facebook failure: {"code":"auth/argument-error","message":"signInWithCredential failed: First argument \"credential\" must be a valid credential."}
It's interesting that it's being caught at the Facebook level instead of the catch I have set up for the auth.login. I have tried passing it in several different ways including as an object { token: success.authResponse.accessToken } and I'm at a loss now. Can anyone help me see what I'm doing wrong? Thanks!
Also, I don't think this is related, but just in case it is I am also receiving a "operation has timed out error" that's not being caught but seems to be thrown by my this.af.auth.subscribe call. The app keeps running fine but perhaps that could be what's making the login fail?
import {Component} from '#angular/core';
import {Platform, ionicBootstrap} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {HomePage} from './pages/home/home';
import {Facebook} from 'ionic-native';
import {
FIREBASE_PROVIDERS, defaultFirebase,
AngularFire, firebaseAuthConfig, AuthProviders,
AuthMethods
} from 'angularfire2';
declare let firebase: any; // <== THERE IS AN ERROR IN THE .d.ts file
#Component({
template: '<ion-nav [root]="rootPage"></ion-nav>',
providers: [
FIREBASE_PROVIDERS,
// Initialize Firebase app
defaultFirebase({}),
firebaseAuthConfig({})
]
})
export class MyApp {
rootPage: any = HomePage;
constructor(platform: Platform, public af: AngularFire) {
platform.ready().then(() => {
// Okay, so the platform is ready and our plugins are available.
// Here you can do any higher level native things you might need.
StatusBar.styleDefault();
Facebook.login(['email'])
.then((_response) => {
console.log(_response)
// IMPORTANT STEP !!
let creds = firebase.auth.FacebookAuthProvider.credential(_response.authResponse.accessToken)
this.af.auth.login(creds,
{
provider: AuthProviders.Facebook,
method: AuthMethods.OAuthToken,
remember: 'default',
scope: ['email'],
})
.then((success) => {
console.log("Firebase success: " + JSON.stringify(success));
alert(JSON.stringify(success))
})
.catch((error) => {
console.log("Firebase failure: " + JSON.stringify(error));
alert(JSON.stringify(error))
});
})
.catch((_error) => { console.log(_error) })
});
}
}
ionicBootstrap(MyApp);
https://github.com/aaronksaunders/AngularFire2-Ionic2-Facebook

Categories