Skip to content

Instantly share code, notes, and snippets.

@wmeints
Last active April 3, 2017 15:52
Show Gist options
  • Save wmeints/d51efe1867066818e5d28b6dd610ae28 to your computer and use it in GitHub Desktop.
Save wmeints/d51efe1867066818e5d28b6dd610ae28 to your computer and use it in GitHub Desktop.
Short demo of how you can wrap standard HTTP behavior by adding additional operations on the observables it produces.
import { ApiRequestOptions } from './api-request-options.service';
import { Http, Response, RequestOptions, ResponseContentType } from '@angular/http';
import 'rxjs/add/observable/zip';
import 'rxjs/add/operator/map';
import { Observable } from 'rxjs/Rx';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
@Injectable()
export class ApiClient {
// PLease note, the API request options service is a helper that we introduced
// to generate absolute URLs based on settings in the client.
// I did not include it here for brevity.
constructor(private router: Router, private http: Http, private requestOptions: ApiRequestOptions) {
}
get<TResponse>(path: string, queryStringParams?: any): Observable<TResponse> {
let self = this;
return Observable.zip(
this.requestOptions.absoluteUrlFor(path, queryStringParams),
this.requestOptions.authorizedRequestOptions()
).flatMap(requestOpts => {
let [url, options] = requestOpts;
return self.http.get(url, options);
}).catch(response => {
if (response.status === 401) {
self.router.navigate(['/login']);
}
return response;
}).map((response: Response) => <TResponse>response.json());
}
post<TResponse>(path: string, body: any): Observable<TResponse> {
let self = this;
return Observable.zip(
this.requestOptions.absoluteUrlFor(path),
this.requestOptions.authorizedRequestOptions()
).flatMap(requestOpts => {
let [url, options] = requestOpts;
return self.http.post(url, body, options);
}).catch(response => {
if (response.status === 401) {
self.router.navigate(['/login']);
}
return response;
}).map((response: Response) => <TResponse>response.json());
}
put<TResponse>(path: string, body: any): Observable<TResponse> {
let self = this;
return Observable.zip(
this.requestOptions.absoluteUrlFor(path),
this.requestOptions.authorizedRequestOptions()
).flatMap(requestOpts => {
let [url, options] = requestOpts;
return self.http.put(url, body, options);
}).catch(response => {
if (response.status === 401) {
self.router.navigate(['/login']);
}
return response;
}).map((response: Response) => {
if (response.status === 200) {
return <TResponse>response.json();
} else {
return null;
}
});
}
delete(path: string): Observable<Response> {
let self = this;
return Observable.zip(
this.requestOptions.absoluteUrlFor(path),
this.requestOptions.authorizedRequestOptions()
).flatMap(requestOpts => {
let [url, options] = requestOpts;
return self.http.delete(url, options);
}).catch(response => {
if (response.status === 401) {
self.router.navigate(['/login']);
}
return response;
});
}
}
import { Injectable } from '@angular/core';
import { ApplicationSettings } from './applicationsettings.service';
import { Observable } from 'rxjs/Rx';
import { AuthenticationService } from '../authentication/authentication.service';
import { Headers, RequestOptions } from '@angular/http';
/**
* Converts the parameters map into a query string for the request
* @param parameters The parameters map to convert
* @returns The querystring for the HTTP request
*/
function asQueryString(parameters: any): string {
let queryStringParameters = [];
for (let key in parameters) {
if (parameters.hasOwnProperty(key) && parameters[key] !== undefined && parameters[key] !== null) {
queryStringParameters.push(`${encodeURI(key)}=${encodeURI(parameters[key])}`);
}
}
return queryStringParameters.join('&');
}
/**
* This service can be used to generate options for API requests
*/
@Injectable()
export class ApiRequestOptions {
/**
* Initializes a new instance of ApiRequestOptions
* @param settings Application settings to use
* @param authenticationService Authentication service for obtaining access tokens
*/
constructor(private settings: ApplicationSettings, private authenticationService: AuthenticationService) {
}
/**
* Generates an absolute URL for a request
* @param path Path for the API endpoint to invoke
* @param queryStringParams Querystring parameters to send
*/
absoluteUrlFor(path: string, queryStringParams?: any): Observable<string> {
let self = this;
return Observable.fromPromise(this.settings.get()).map(settings => {
let absoluteUrl = settings.prescreeningApi.serviceUrl + path;
if (queryStringParams) {
absoluteUrl = absoluteUrl + '?' + asQueryString(queryStringParams);
}
return absoluteUrl;
});
}
/**
* Generates authorized request options
* @returns {Observable<R>} An observable with the necessary request options
*/
authorizedRequestOptions() {
return this.authenticationService.getUser().map(user => {
let headers = new Headers({
'Authorization': `Bearer ${user.access_token}`
});
return new RequestOptions({ headers: headers });
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment