ohayolibs
Version:
Ohayo is a set of essential modules for ohayojp.
120 lines (107 loc) • 3.89 kB
text/typescript
import {
HttpBackend,
HttpErrorResponse,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
HttpResponse,
HttpResponseBase,
HTTP_INTERCEPTORS,
} from '@angular/common/http';
import { Injectable, Injector } from '@angular/core';
import { deepCopy } from '@ohayo/util';
import { Observable, of, throwError } from 'rxjs';
import { delay } from 'rxjs/operators';
import { MockRequest } from './interface';
import { MockService } from './mock.service';
import { MockStatusError } from './status.error';
class HttpMockInterceptorHandler implements HttpHandler {
constructor(private next: HttpHandler, private interceptor: HttpInterceptor) { }
handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
return this.interceptor.intercept(req, this.next);
}
}
()
export class MockInterceptor implements HttpInterceptor {
constructor(private injector: Injector) { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const src = this.injector.get(MockService);
const config = src.config;
const rule = src.getRule(req.method, req.url.split('?')[0]);
if (!rule && !config.force) {
return next.handle(req);
}
let res: any;
switch (typeof rule!.callback) {
case 'function':
const mockRequest: MockRequest = {
original: req,
body: req.body,
queryString: {},
headers: {},
params: rule!.params,
};
const urlParams = req.url.split('?');
if (urlParams.length > 1) {
urlParams[1].split('&').forEach(item => {
const itemArr = item.split('=');
const key = itemArr[0];
const value = itemArr[1];
// is array
if (Object.keys(mockRequest.queryString).includes(key)) {
if (!Array.isArray(mockRequest.queryString[key])) {
mockRequest.queryString[key] = [mockRequest.queryString[key]];
}
mockRequest.queryString[key].push(value);
} else {
mockRequest.queryString[key] = value;
}
});
}
req.params.keys().forEach(key => (mockRequest.queryString[key] = req.params.get(key)));
req.headers.keys().forEach(key => (mockRequest.headers[key] = req.headers.get(key)));
try {
res = rule!.callback.call(this, mockRequest);
} catch (e) {
res = new HttpErrorResponse({
url: req.url,
headers: req.headers,
status: e instanceof MockStatusError ? e.status : 400,
statusText: e.statusText || 'Unknown Error',
error: e.error,
});
}
break;
default:
res = rule!.callback;
break;
}
if (!(res instanceof HttpResponseBase)) {
res = new HttpResponse({
status: 200,
url: req.url,
body: res,
});
}
if (res.body) {
res.body = deepCopy(res.body);
}
if (config.log) {
console.log(`%c👽${req.method}->${req.urlWithParams}->request`, 'background:#000;color:#bada55', req);
console.log(`%c👽${req.method}->${req.urlWithParams}->response`, 'background:#000;color:#bada55', res);
}
const res$ = res instanceof HttpErrorResponse ? throwError(res) : of(res);
if (config.executeOtherInterceptors) {
const interceptors = this.injector.get(HTTP_INTERCEPTORS, []);
const lastInterceptors = interceptors.slice(interceptors.indexOf(this) + 1);
if (lastInterceptors.length > 0) {
const chain = lastInterceptors.reduceRight((_next, _interceptor) => new HttpMockInterceptorHandler(_next, _interceptor), {
handle: () => res$,
} as HttpBackend);
return chain.handle(req).pipe(delay(config.delay!));
}
}
return res$.pipe(delay(config.delay!));
}
}