Could we introduce an example of how to use the HttpInterceptor with NgRX Store for adding authentication headers onto requests using the new HttpClient released in angular 4.3?
Definitely!
I'm working on having the transfer and retrieval of data & cache, even the origin_url, all be handled with the Interceptor to make things a bit cleaner. 馃憤
I'm not sure if this is the best way, but so far I'm using this. Basically I have some Ngrx Effects. On load I authenticate the user and keep the token in the ngrx store with the user state. Then I pass this on via subscribing to the store in the Interceptor.
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private userState: UserState;
constructor(private store: Store<AppState>) {
store.select<UserState>((s) => s.user).subscribe(userState => this.userState = userState);
}
public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.userState.authenticated) {
const authReq = req.clone({ headers: req.headers.set('Authorization', this.userState.user.token_type + ' ' + this.userState.user.access_token) });
return next.handle(authReq);
}
return next.handle(req);
}
}
All I needed to do was update the TransferHttp class to use the new HttpClient. I also defined some types to help make it feel more typed.
type HttpClientOptions = {
body?: any;
headers?: HttpHeaders,
observe?: 'body',
params?: HttpParams,
responseType?: 'json',
reportProgress?: boolean,
withCredentials?: boolean
};
type HttpCallback = (uri: string | Request, options?: any) => Observable<Object>;
type HttpPostCallback = (uri: string | Request, body: any, options?: any) => Observable<Object>;
This allows me to have it looking like this in the TransferHttp class... (need to omit the usage of response.json() since this is now handled inside the HttpClient
public get<T>(url: string, options?: HttpClientOptions): Observable<T> {
return this.getData(url, options, (url: string, options: HttpClientOptions) => this.httpClient.get<T>(url, options));
}
Very nice! I don't see anything wrong with that implementation 馃憤 Is everything working smoothly?
Also, love the types for HttpClientOptions, that makes it real nice.
I'll ping you when I get my implementation in here so you can see if any different than what you have. Hopefully we can make it look like we are using normal Http, and it just takes care of so many other things for us.
It's working just fine for me in the Browser.
Not quite sure where the best place is to be pulling in the HttpClientModule, AppModule is pulled in before BrowserModule and they suggest pulling in the HttpClientModule after the BrowserModule
Some other modules still depend on HttpModule like the Translation stuff, so I left that where it was. I ended up importing the HttpClientModule in our TransferHttpModule.
I have SSR turned off, so not sure on that side of things.
One thing I find a bit weird is, im handling errors (Server went BANG) in my ngrx Effects, but i am returning a HTTP Status of 500 with the response containing a Body with some content (i.e actual specific reason why it went bang) but the HttpErrorResponse object from the HttpClient in Angular doesn't seem to store this...very annoying
It can't be found anywhere in the error, what comes up if you console log the entire Error object you get back? Hmm, are you catching the error somewhere else maybe?
Unrelated but I noticed TranslateModule npm package has an update which takes the new HttpClient. So that's also a simple quick code change for the translation piece. :)
@pjmagee what does your transfer-http look like now?
Sweet, how is this working for you in general? Are you using interceptors at all? I am putting together a JWT one for all POST, PUT, DELETE.
Well, I think my current implementation is pretty poor. I'm using an npm package called oidc-client and i have a service that basically creates this client and handles the tokens for me. It has some built in events which you can wire some callback functions to, I wire these callback/events to some store dispatchers and store the user/authentication token in my ngrx store.
basically something like below:
this.manager.events.addUserLoaded((user) => this.dispatcher.userLoaded(user));
this.manager.events.addUserSignedOut(() => this.dispatcher.loggedOut());
this.manager.events.addUserUnloaded(() => this.dispatcher.expired());
this.manager.events.addAccessTokenExpired(() => this.dispatcher.expired());
Then I use the AuthInterceptor code I pasted at the top of this issue as a way to pass my jwt token as a header.
However, things are working. The best way? No idea. Could it be better? Probably. Do i know what I'm even doing? No :)
Does your HttpClient code actually fire on the server side? I have been trying to get it to work, but best I can tell HttpClient.get calls are totally ignored by Node during server-side rendering which makes the cache not work.
It is working for me :)
My HttpClient issues were caused by turning windows authentication on in my project not server-side rendering. Argh.
@MarkPieszak I am going to close this and put it in the META Issue to upgrade Angular
What about having HttpInterceptor to handle cache http response on server instead of having transfer-http.module at all, an approach similar to this:
I was going to add that in there, but with 5.0 Vikram took the TransferHttp and basically added it into Core so it'll be much easier to do it then. Once 5.0 comes out we can add it!
I need to make a few updates to the engine as well to accommodate changes in 5.0, but I'll make sure to get that in there with it!