/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.io/license */ import {XhrFactory} from '@angular/common'; import {HttpBackend, HttpEvent, HttpHeaders, HttpParams, HttpRequest, HttpResponse, HttpXhrBackend} from '@angular/common/http'; import {Inject, Injectable, Optional} from '@angular/core'; import {Observable} from 'rxjs'; import {map} from 'rxjs/operators'; import {BackendService} from './backend-service'; import {STATUS} from './http-status-codes'; import {InMemoryBackendConfig, InMemoryBackendConfigArgs, InMemoryDbService, ResponseOptions} from './interfaces'; /** * For Angular `HttpClient` simulate the behavior of a RESTy web api * backed by the simple in-memory data store provided by the injected `InMemoryDbService`. * Conforms mostly to behavior described here: * https://www.restapitutorial.com/lessons/httpmethods.html * * ### Usage * * Create an in-memory data store class that implements `InMemoryDbService`. * Call `config` static method with this service class and optional configuration object: * ``` * // other imports * import { HttpClientModule } from '@angular/common/http'; * import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api'; * * import { InMemHeroService, inMemConfig } from '../api/in-memory-hero.service'; * @NgModule({ * imports: [ * HttpModule, * HttpClientInMemoryWebApiModule.forRoot(InMemHeroService, inMemConfig), * ... * ], * ... * }) * export class AppModule { ... } * ``` */ @Injectable() export class HttpClientBackendService extends BackendService implements HttpBackend { constructor( inMemDbService: InMemoryDbService, @Inject(InMemoryBackendConfig) @Optional() config: InMemoryBackendConfigArgs, private xhrFactory: XhrFactory) { super(inMemDbService, config); } handle(req: HttpRequest): Observable> { try { return this.handleRequest(req); } catch (error) { const err = error.message || error; const resOptions = this.createErrorResponseOptions(req.url, STATUS.INTERNAL_SERVER_ERROR, `${err}`); return this.createResponse$(() => resOptions); } } protected getJsonBody(req: HttpRequest): any { return req.body; } protected getRequestMethod(req: HttpRequest): string { return (req.method || 'get').toLowerCase(); } protected createHeaders(headers: {[index: string]: string;}): HttpHeaders { return new HttpHeaders(headers); } protected createQueryMap(search: string): Map { const map = new Map(); if (search) { const params = new HttpParams({fromString: search}); params.keys().forEach(p => map.set(p, params.getAll(p) || [])); } return map; } protected createResponse$fromResponseOptions$(resOptions$: Observable): Observable> { return resOptions$.pipe(map(opts => new HttpResponse(opts))); } protected createPassThruBackend() { try { return new HttpXhrBackend(this.xhrFactory); } catch (ex) { ex.message = 'Cannot create passThru404 backend; ' + (ex.message || ''); throw ex; } } }