Okay suppose I have auth guard.
I want to do just a simple thing: send request to backend, in case it sends me user info that means user is authenticated, I want to return true. Else it will send me the error, so I want to catch that error and redirect user.
How do I do it in with rxjs? It seems overcomplicated...
What I want to do is to check whether user is logged in and whether his token is valid. So I understand that I need to send a request but how to manager error or response in general then? I understand too, that if there is no token in local storage, I should return false and shouldn't even send any request.
Of course this doesn't work but I don't know how to do it at all...
// guard
return this.authService.checkUserAuthenticated();
// service
checkUserAuthenticated() {
this.http.post(`${this.domainName}api/auth/userinfo`, null)
.subscribe(
(data) => true,
(err) => false
);
}
you can make an api call to the backend using authguard then return true or false
export class AuthGuard implements CanActivate {
constructor(private router: Router, private service:Service) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): boolean {
this.service.Authenticate().subscribe(
(data: any)=>{ any condition to check and then return true},
(error: any)=>{ return false;});
}
}
and add authguard authentication method to the routing file.
Related
i want to show a message in my authentification page when my token expires.
the app has a guard that checks in every request if user is still authenticated or not(token is still valid or not).
my problem is when i used localstorage and session storageto store the variable "expired". expired has always true since it's stored in the navigator. Any other solutions?
I am new to angular so please any help ?
what i want to show in my login page if expired is true:
<span *ngIf="expired" class="help-block text-danger">
Votre session a expiré !
</span>
and here is the guard code :
#Injectable()
export class AuthGuard implements CanActivateChild {
constructor(private router: Router, private localSt:
LocalStorageService, private loginService: LoginService) {
}
canActivateChild(childRoute: ActivatedRouteSnapshot, state:
RouterStateSnapshot) {
if (this.loginService.isAuthenticated()) {
sessionStorage.setItem("expired", 'false');
return true;
}
sessionStorage.setItem("expired", 'true');
this.router.navigate(['/login']);
return false;
}
}
what I do to show "The session has expired" is:
If the user is idle, or navigating to a URL without the proper permissions I send him/her to the login page through a function on a shared service
endSesion( message ) {
window.localStorage.clear(); //to clear all session variables, tokens and stuff
window.localStorage.setItem('message',message) // save as the only left thing in LS
this.router.navigate(['login']);
}
And in the constructor or the ngOnInit of the login component
ngOnInit() {
this.message = window.localStorage.getItem('message'); // get the message from LS
if ( this.message ) {
alert('Dude!: ' + this.message ); //maybe sweetalert will be nicer to look at
}
}
This way you dont only use to throw user out beacuse a session expired but maybe if not permission or maybe if you check another security issue even froma backend response.
I am doing http client request
export class MapjsonService{
theUrl = 'http://localhost:4200/api/Lat_Long.json';
constructor(private http: HttpClient) { }
fetchNews(): Observable<any>{
return this.http.get(this.theUrl)
}
It is working about 99.99% of the time sadly this is running so often that is fails like once every 10 mins with
HttpErrorResponse {headers: HttpHeaders, status: 200, statusText: "OK", url: "http://localhost:4200/api/Lat_Long.json", ok: false, …}
and
"Http failure during parsing for http://localhost:4200/api/Lat_Long.json"
Now I figured out for some reason my nrql query from newrelic (which is what is being stored in '/api/lat_long.json' does not have the final closing '}' once every orange moon. and this is what is throwing this error. my question is there any whay for me to check if the returned value is valid json and if it is not try the GET request again without terminating the process that called it. Thx
Your code is throwing an error because the json is not correct, therefore it can't be parsed, and therefore the observable throws an error:
fetchNews(): Observable<any>{
return this.http.get(this.theUrl)
}
By default, the http client expect json because that's usually what users expect from it. It's not always the case, like the situation you are in right now.
We can tell the http client not to parse the json on its own by specifying what we want from it using the {responseType: 'text'} parameter.
fetchNews(): Observable<any>{
return this.http.get(this.theUrl, {responseType: 'text'})
}
But then you need to parse the json when possible. So we will map the observable and parse the content here if possible.
fetchNews(): Observable<any>{
return this.http.get(this.theUrl, {responseType: 'text'}).map(res => {
try{
return JSON.parse(res);
} catch {
return null;
}
})
}
Then do whatever you want, the value returned by the observable will be null if it can't be parsed.
RXJS 6 syntax:
fetchNews(): Observable<any>{
return this.http.get(this.theUrl, {responseType: 'text'}).pipe(
map(res => {
try{
return JSON.parse(res);
} catch {
return null;
}
})
)
}
I am looking for data in an API via Get request, I need the data inside my OnInit to use in composing other data. The problem is that the method is being called but it is as an async method (without await), it passes everywhere but when the return is obtained the excution of the main method has already been finished with no results. I tried the implementation of asynchronous methods but it did not solve.
service:
getObjects(): MyClass[] {
let objects = new Array<MyClass>();
this.obterTodos<MyClass>(this.uriApi)
.map(res => res.map(x => new MyClass(x.Description, x.Id)))
.subscribe(entities => {
objects = entities;
});
return objects ;
}
get request
public getObjects<TEntity>(url: string): Observable<TEntity[]> {
return this.httpService
.get(this.serviceUrl + url, this.options)
.map(res => res.json())
.catch(this.handleError);
}
component:
ngOnInit() {
this.myObjects= this.setorService.obterSetores();
console.log('this.myObjects is empty here');
}
so you'll want to subscribe to your observable in the component. This is typically done so the component can determine when the http request should be ran & so the component can wait for the http request to finish (and follow with some logic).
// subscribe to observable somewhere in your component (like ngOnInit)
this.setorService.obterSetores().subscribe(
res => {
this.myObjects = res;
},
err => {}
)
now the component knows when the http request finishes
I have service which returns an observable which does an http request to my server and gets the data. I want to use this data but I always end up getting undefined. What's the problem?
Service:
#Injectable()
export class EventService {
constructor(private http: Http) { }
getEventList(): Observable<any>{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get("http://localhost:9999/events/get", options)
.map((res)=> res.json())
.catch((err)=> err)
}
}
Component:
#Component({...})
export class EventComponent {
myEvents: any;
constructor( private es: EventService ) { }
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
});
console.log(this.myEvents); //This prints undefined!
}
}
I checked How do I return the response from an asynchronous call? post but couldn't find a solution
Reason:
The reason that it's undefined is that you are making an asynchronous operation. Meaning it'll take some time to complete the getEventList method (depending mostly on your network speed).
So lets look at the http call.
this.es.getEventList()
After you actually make ("fire") your http request with subscribe you will be waiting for the response. While waiting, javascript will execute the lines below this code and if it encounters synchronous assignments/operations it'll execute them immediately.
So after subscribing to the getEventList() and waiting for the response,
console.log(this.myEvents);
line will be executed immediately. And the value of it is undefined before the response arrives from the server (or to whatever that you have initialized it in the first place).
It is similar to doing:
ngOnInit(){
setTimeout(()=>{
this.myEvents = response;
}, 5000);
console.log(this.myEvents); //This prints undefined!
}
**Solution:**
>So how do we overcome this problem? We will use the callback function which is the `subscribe` method. Because when the data arrives from the server it'll be inside the `subscribe` with the response.
So changing the code to:
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //<-- not undefined anymore
});
will print the response.. after some time.
**What you should do:**
There might be lots of things to do with your response other than just logging it; you should do all these operations inside the callback (inside the subscribe function), when the data arrives.
Another thing to mention is that if you come from a Promise background, the then callback corresponds to subscribe with observables.
**What you shouldn't do:**
You shouldn't try to change an async operation to a sync operation (not that you can). One of the reasons that we have async operations is to not make the user wait for an operation to complete while they can do other things in that time period. Suppose that one of your async operations takes 3 minutes to complete, if we didn't have the async operations then the interface would freeze for 3 minutes.
Suggested Reading:
The original credit to this answer goes to: How do I return the response from an asynchronous call?
But with the angular2 release we were introduced to typescript and observables so this answer hopefully covers the basics of handling an asynchronous request with observables.
Making a http call in angular/javascript is asynchronous operation.
So when you make http call it will assign new thread to finish this call and start execution next line with another thread.
That is why you are getting undefined value.
so make below change to resolve this
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //<-this become synchronous now
});
You can use asyncPipe if you use myEvents only in template.
Here example with asyncPipe and Angular4 HttpClient example
Observables are lazy so you have to subscribe to get the value. You subscribed it properly in your code but simultaneously logged the output outside the 'subscribe' block. That's why it is 'undefined'.
ngOnInit() {
this.es.getEventList()
.subscribe((response) => {
this.myEvents = response;
});
console.log(this.myEvents); //Outside the subscribe block 'Undefined'
}
So if you log it inside the subscribe block then it will log response properly.
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //Inside the subscribe block 'http response'
});
}
Here the problem is, you are initializing this.myEvents into subscribe() which is an asynchronous block while you are doing console.log() just out of subscribe() block.
So console.log() getting called before this.myEvents gets initialized.
Please move your console.log() code as well inside subscribe() and you are done.
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents);
});
}
The result is undefined because angular process async .
you can trying as below:
async ngOnInit(){
const res = await this.es.getEventList();
console.log(JSON.stringify(res));
}
Also make sure that you map your response to a json output. Otherwise it will return plain text. You do it this like this:
getEventList(): Observable<any> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get("http://localhost:9999/events/get", options)
.map((res)=>{ return res.json();}) <!-- add call to json here
.catch((err)=>{return err;})
}
Undefined because the value here is logged before any data from the service is set from that above subscribe service call. So you have to wait until the ajax call finishes and set the data from the response data.
getEventList(): Observable<any>{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get("http://localhost:9999/events/get", options)
.map((res)=> res.json())
.catch((err)=> err)
}
Here make the Console log inside the subscribe method that will make the log when the data is set in myEvents variable.
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
// This prints the value from the response
console.log(this.myEvents)
});
}
To do this you have 2 options:
Suppose we have a service which is returning shipping details array :
getShippingPrices(): Observable<IShippingDetails[]> {
return this.http.get<IShippingDetails[]>('/assets/shipping.json');
}
1. Use Async pipe : Easy way when you just want to show the result in template
In the component class directly assign the observable to variable:
export class ShippingComponent implements OnInit {
shipOptions1 = this.cartService.getShippingPrices();
constructor(private cartService: CartService) {}
ngOnInit() {}
}
and then use async pipe in template :
<div *ngFor="let s of shipOptions1 |async">
<label>{{s.type}}</label>
</div>
Refer: Check the 4th point in this URL
https://angular.io/start/start-data#configuring-the-shippingcomponent-to-use-cartservice
2. Use Subscribe : When you want to manipulate it or want do some business logic on/from response
export class ShippingComponent implements OnInit {
shipOptions2: IShippingDetails[] = [];
constructor(private cartService: CartService) {}
ngOnInit() {
this.cartService.getShippingPrices().subscribe(response => {
this.shipOptions2 = response;
//console.log(this.myEvents);
//All other code using shipOptions2
});
}
}
You can simply try this method-
let headers = new Headers({'Accept': 'application/json'});
let options = new RequestOptions({headers: headers});
return this.http
.get(this.yourSearchUrlHere, options) // the URL which you have defined
.map((res) => {
res.json(); // using return res.json() will throw error
}
.catch(err) => {
console.error('error');
}
I'm new to REST services, I have an Angular2 client calling a RestEasy JAX-RS service. All I am trying to get is a "Hello World" message in JSON format. I was expecting only a JSON object, but I get my response with the following structure:
_body: "{"message":"Hello World!!"}"
headers: t
ok: true
status: 200
statusText: "OK"
type: 2
url: "http://localhost:8080/helloapp/rest/hello/world"
__proto__: ...
My question is, Is that the way it should be?
I mean, I thought I would be able to access the JSON object straight from the response. Something like
this.service.getHello()
.then( result => {
console.log(JSON.parse(result)); //{message: "Hello World"}
this.message = JSON.parse(result).message;
});
But I actually have to get it from _body:
this.service.getHello()
.then( result => {
this.message = JSON.parse(result._body).message;
console.log(this.message);//Hello World
});
Is it a RestEasy configuration thing, is there a way to change that?
Or
Should I consider that I will always have a field _body in my response with my data, and that's the default response structure?
For eventual consideration, here is my backend code:
HelloWorld Service:
#Path("/hello")
#Produces({ "application/json" })
#Consumes({ "application/json" })
public class HelloWorld {
public HelloWorld() {}
#GET
#Path("/world")
public Message getHello(){
return new Message("Hello World!!");
}
}
My RestEasy version is 3.1.1.Final running in Wildfly 10.1.0.Final
What you're getting back is the Response object from the Http request. This is what all Http operations will return. The easiest way to parse the JSON from that is to just call the json() method on it
this.service.getHello()
.then((res: Response) => {
let obj = res.json();
});
If you want the getHello to just return the object without having to parse it (on the calling client), then you can do it inside the getHello method by mapping it (using the Observable.map operation)
getHello() {
this.http.get(..)
.map((res: Response) => res.json())
.toPromise();
}
As peeskillet says above, you're getting back the entire Response from the request, and while sometimes you may want to examine the headers, perhaps to handle the different return conditions (retry or redirect on 4xx or 5xx responses for example), most of the time we assume a successful request and we just want the payload.
Angular2 encourages the use of Observables, so your service might look something like this:
getHello()
{
return this.http.get(http://localhost:8080/helloapp/rest/hello/world)
}
And your component may look something like this:
data: string;
ngOnInit() {
this.service
.getHello()
.map(response => response.json())
.subscribe (
data => {
this.data = data,
},
err => console.log('Error',err),
() => console.log('data',this.data)
);
}
You call the service, which is an http.get() and returns an Observable object, and we use .map to parse the response as JSON, which also returns an Observable, which we subscribe to.
Subscribe has three callback functions,
.subscribe(success, failure, complete)
In the example above on success we assign the payload - data - to this.data, if the subscribe fails, you log the error, and when it completes, we can do whatever we like, but in this case, we log this.data to the console - that's optional, but I log out the results while developing and then strip them out later.