Skip to content

Commit

Permalink
feature(http): new http (#62)
Browse files Browse the repository at this point in the history
* removed provideInterceptors()

* polished httpInterceptorService and fixed bugs in interceptor pipeline

* change properties in IRestQuery to any type

* added ngModule to http module, and provided interceptors with forRoot() to be inline with angular

* updated docs with ngmodule notation for http module

* reword example to setup in http module

* created http.module.ts for CovalentHttpModule

* updated README.md
  • Loading branch information
emoralesb05 authored and kyleledbetter committed Sep 13, 2016
1 parent 13110bf commit 91050c5
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 98 deletions.
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { appRoutes, appRoutingProviders } from './app.routes';
import { CovalentCoreModule, TD_LOADING_ENTRY_COMPONENTS } from '../platform/core';
import { CovalentFileModule } from '../platform/file-upload';
import { CovalentHighlightModule } from '../platform/highlight';
import { CovalentHttpModule } from '../platform/http';
import { CovalentMarkdownModule } from '../platform/markdown';
import { CovalentJsonFormatterModule } from '../platform/json-formatter';
import { CovalentChipsModule } from '../platform/chips';
Expand All @@ -27,6 +28,7 @@ import { CovalentChipsModule } from '../platform/chips';
StyleGuideModule,
CovalentCoreModule.forRoot(),
CovalentFileModule.forRoot(),
CovalentHttpModule.forRoot(),
CovalentHighlightModule,
CovalentMarkdownModule,
CovalentJsonFormatterModule,
Expand Down
23 changes: 14 additions & 9 deletions src/app/components/components/http/http.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ <h3 md-line> {{attr.name}}: <span>{{attr.type}}</span></h3>
<md-divider *ngIf="!last"></md-divider>
</template>
</md-list>
<h3>Example:</h3>
<p>Typescript:</p>
<h3>Setup:</h3>
<p>Create your custom interceptors by implementing [IHttpInterceptor]:</p>
<td-highlight lang="typescript">
<![CDATA[
import { Injectable } from '@angular/core';
Expand All @@ -51,17 +51,22 @@ <h3>Example:</h3>
}
]]>
</td-highlight>
<p>Bootstrap interceptor providers:</p>
<p>Then, import the [CovalentHttpModule] using the <code>forRoot()</code> method with the desired interceptors in your NgModule:</p>
<td-highlight lang="typescript">
<![CDATA[
import { HTTP_PROVIDERS } from '@angular/http';
import { provideInterceptors } from '@covalent/http';
import { HttpModule } from '@angular/http';
import { CovalentHttpModule } from '@covalent/http';
import { CustomInterceptor } from 'dir/to/interceptor';

bootstrap(AppComponent, [
HTTP_PROVIDERS,
provideInterceptors([CustomInterceptor]),
]);
@NgModule({
imports: [
HttpModule, /* or CovalentCoreModule.forRoot() */
CovalentHttpModule.forRoot([CustomInterceptor]),
...
],
...
})
export class MyModule {}
]]>
</td-highlight>
<p>After that, just inject [HttpInterceptorService] and use it for your requests.</p>
Expand Down
24 changes: 15 additions & 9 deletions src/platform/http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ export interface IHttpInterceptor {
```
Every method is optional, so you can just implement the ones that are needed.

Example:
## Setup

Create your custom interceptors by implementing [IHttpInterceptor]:

```typescript
import { Injectable } from '@angular/core';
Expand All @@ -56,17 +58,21 @@ export class CustomInterceptor implements IHttpInterceptor {

```

Also, you need to bootstrap the interceptor providers
Then, import the [CovalentHttpModule] using the forRoot() method with the desired interceptors in your NgModule:

```typescript
import { HTTP_PROVIDERS } from '@angular/http';
import { provideInterceptors } from '@covalent/http';
import { HttpModule } from '@angular/http';
import { CovalentHttpModule } from '@covalent/http';
import { CustomInterceptor } from 'dir/to/interceptor';

bootstrap(AppComponent, [
HTTP_PROVIDERS,
provideInterceptors([CustomInterceptor]),
]);
@NgModule({
imports: [
HttpModule, /* or CovalentCoreModule.forRoot() */
CovalentHttpModule.forRoot([CustomInterceptor]),
...
],
...
})
export class MyModule {}
```

After that, just inject [HttpInterceptorService] and use it for your requests.
Expand Down
108 changes: 30 additions & 78 deletions src/platform/http/http-interceptor.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Injectable, Type, ValueProvider, Injector } from '@angular/core';
import { Injectable, Type, Injector } from '@angular/core';
import { Http, RequestOptionsArgs, Response, Request } from '@angular/http';

import { Observable } from 'rxjs/Observable';
Expand All @@ -13,127 +13,79 @@ export interface IHttpInterceptor {
@Injectable()
export class HttpInterceptorService {

requestInterceptors: IHttpInterceptor[] = [];
private _requestInterceptors: IHttpInterceptor[] = [];

constructor(private _http: Http, private _injector: Injector, requestInterceptors: Type<any>[]) {
requestInterceptors.forEach((interceptor: Type<any>) => {
this.requestInterceptors.push(<IHttpInterceptor>_injector.get(interceptor));
this._requestInterceptors.push(<IHttpInterceptor>_injector.get(interceptor));
});
}

request(url: string | Request, options: RequestOptionsArgs = {}): Observable<Response> {
this._requestConfig(options);
return this._http.request(url, options)
.do((response: Response) => {
return this._responseResolve(response);
}).catch((error: Response) => {
return this._errorResolve(error);
});
return this._setupRequest(this._http.request(url, this._requestResolve(options)));
}

delete(url: string, options: RequestOptionsArgs = {}): Observable<Response> {
this._requestConfig(options);
return this._http.delete(url, options)
.do((response: Response) => {
return this._responseResolve(response);
}).catch((error: Response) => {
return this._errorResolve(error);
});
return this._setupRequest(this._http.delete(url, this._requestResolve(options)));
}

get(url: string, options: RequestOptionsArgs = {}): Observable<Response> {
this._requestConfig(options);
return this._http.get(url, options)
.do((response: Response) => {
return this._responseResolve(response);
}).catch((error: Response) => {
return this._errorResolve(error);
});
return this._setupRequest(this._http.get(url, this._requestResolve(options)));
}

head(url: string, options: RequestOptionsArgs = {}): Observable<Response> {
this._requestConfig(options);
return this._http.head(url, options)
.do((response: Response) => {
return this._responseResolve(response);
}).catch((error: Response) => {
return this._errorResolve(error);
});
return this._setupRequest(this._http.head(url, this._requestResolve(options)));
}

patch(url: string, data: any, options: RequestOptionsArgs = {}): Observable<Response> {
this._requestConfig(options);
return this._http.patch(url, data, options)
.do((response: Response) => {
return this._responseResolve(response);
}).catch((error: Response) => {
return this._errorResolve(error);
});
return this._setupRequest(this._http.patch(url, data, this._requestResolve(options)));
}

post(url: string, data: any, options: RequestOptionsArgs = {}): Observable<Response> {
this._requestConfig(options);
return this._http.post(url, data, options)
.do((response: Response) => {
return this._responseResolve(response);
}).catch((error: Response) => {
return this._errorResolve(error);
});
return this._setupRequest(this._http.post(url, data, this._requestResolve(options)));
}

put(url: string, data: any, options: RequestOptionsArgs = {}): Observable<Response> {
this._requestConfig(options);
return this._http.put(url, data, options)
.do((response: Response) => {
return this._responseResolve(response);
return this._setupRequest(this._http.put(url, data, this._requestResolve(options)));
}

private _setupRequest(responseObservable: Observable<Response>): Observable<Response> {
return new Observable<any>((subscriber: Subscriber<any>) => {
responseObservable.do((response: Response) => {
subscriber.next(this._responseResolve(response));
}).catch((error: Response) => {
return this._errorResolve(error);
});
return new Observable<any>(() => {
subscriber.error(this._responseErrorResolve(error));
});
}).subscribe();
});
}

private _requestConfig(requestOptions: RequestOptionsArgs): void {
this.requestInterceptors.forEach((interceptor: IHttpInterceptor) => {
private _requestResolve(requestOptions: RequestOptionsArgs): RequestOptionsArgs {
this._requestInterceptors.forEach((interceptor: IHttpInterceptor) => {
if (interceptor.onRequest) {
requestOptions = interceptor.onRequest(requestOptions);
}
});
return requestOptions;
}

private _responseResolve(response: Response): Observable<Response> {
this.requestInterceptors.forEach((interceptor: IHttpInterceptor) => {
private _responseResolve(response: Response): Response {
this._requestInterceptors.forEach((interceptor: IHttpInterceptor) => {
if (interceptor.onResponse) {
response = interceptor.onResponse(response);
}
});
return new Observable<any>((subscriber: Subscriber<any>) => {
subscriber.next(response);
});
return response;
}

private _errorResolve(error: Response): Observable<Response> {
this.requestInterceptors.forEach((interceptor: IHttpInterceptor) => {
private _responseErrorResolve(error: Response): Response {
this._requestInterceptors.forEach((interceptor: IHttpInterceptor) => {
if (interceptor.onResponseError) {
error = interceptor.onResponseError(error);
}
});
return new Observable<any>((subscriber: Subscriber<any>) => {
subscriber.error(error);
});
return error;
}

}

export function provideInterceptors(requestInterceptors: Type<any>[] = []): any[] {
let providers: any[] = [];
requestInterceptors.forEach((interceptor: Type<any>) => {
providers.push(interceptor);
});
providers.push({
provide: HttpInterceptorService,
useFactory: (http: Http, injector: Injector): HttpInterceptorService => {
return new HttpInterceptorService(http, injector, requestInterceptors);
},
deps: [Http, Injector],
});
return providers;
}
2 changes: 1 addition & 1 deletion src/platform/http/http-rest.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface IRestConfig {
}

export interface IRestQuery {
[key: string]: boolean | number | string;
[key: string]: any;
}

export interface IHttp {
Expand Down
32 changes: 32 additions & 0 deletions src/platform/http/http.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { NgModule, ModuleWithProviders, Type, Injector } from '@angular/core';
import { HttpModule, Http } from '@angular/http';

import { HttpInterceptorService } from './http-interceptor.service';

@NgModule({
imports: [
HttpModule,
],
providers: [
HttpInterceptorService,
],
})
export class CovalentHttpModule {
static forRoot(requestInterceptors: Type<any>[] = []): ModuleWithProviders {
let providers: any[] = [];
requestInterceptors.forEach((interceptor: Type<any>) => {
providers.push(interceptor);
});
providers.push({
provide: HttpInterceptorService,
useFactory: (http: Http, injector: Injector): HttpInterceptorService => {
return new HttpInterceptorService(http, injector, requestInterceptors);
},
deps: [Http, Injector],
});
return {
ngModule: CovalentHttpModule,
providers: providers,
};
}
}
3 changes: 2 additions & 1 deletion src/platform/http/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { RESTService, IRestTransform, IRestConfig, IRestQuery, IHttp } from './http-rest.service';
export { IHttpInterceptor, HttpInterceptorService, provideInterceptors } from './http-interceptor.service';
export { IHttpInterceptor, HttpInterceptorService } from './http-interceptor.service';
export { CovalentHttpModule } from './http.module';

0 comments on commit 91050c5

Please sign in to comment.