Skip to content

Instantly share code, notes, and snippets.

@TakuyaAbe
Last active March 23, 2018 09:36
Show Gist options
  • Save TakuyaAbe/660b9376e77d278d49e49d168ea80b60 to your computer and use it in GitHub Desktop.
Save TakuyaAbe/660b9376e77d278d49e49d168ea80b60 to your computer and use it in GitHub Desktop.
fake-backend module based on angular-5-mock-backend-example-for-backendless-development
// http://jasonwatmore.com/post/2017/12/15/angular-5-mock-backend-example-for-backendless-development
import { Injectable } from '@angular/core';
import { HttpRequest, HTTP_INTERCEPTORS } from '@angular/common/http';
import { FakeBackendInterceptorBase } from 'src/app/fake-backends/fake-backend-base';
import { LoggerService } from 'src/libs/logger/src/logger.module';
const LOGIN_PATH = '/cmn/auth/login';
const LOGOUT_PATH = '/cmn/auth/logout';
@Injectable()
export class FakeBackendAuth extends FakeBackendInterceptorBase {
constructor(protected logger: LoggerService) {
super(logger);
}
responseBodyBulider(request: HttpRequest<any>) {
const loginResBody = {
accessToken: 'dummyAccessToken',
refreshToken: 'dummyRefreshToken',
userId: 'xxx',
parentUserId: 'xxx',
language: 'xxx',
username: 'xxx',
};
const DUMMY_PASSWORD = 'xxx';
const DUMMY_userId = 'yyy';
if (request.url.endsWith(LOGIN_PATH) && request.method === 'POST') {
if (request.body.userId === DUMMY_userId && request.body.password === DUMMY_PASSWORD) {
// if login details are valid return 200 OK with user details and fake jwt token
const body = loginResBody;
this.logger.info(`FAKE RES of ${request.url}`, body);
return { status: 200, body: body };
} else {
// else return 400 bad request
return { status: 400, body: 'invalid auth info' };
}
}
// logout
if (request.url.endsWith(LOGOUT_PATH) && request.method === 'POST') {
// check for fake auth token in header and return user if valid, this security is implemented server side in a real application
if (request.headers.get('Authorization') === 'Bearer fake-jwt-token') {
return { status: 200, body: true };
} else {
// return 401 not authorised if token is null or invalid
return { status: 200, body: false };
}
}
}
}
export let cmnAuthFakeBackendProvider = {
// use fake backend in place of Http service for backend-less development
provide: HTTP_INTERCEPTORS,
useClass: FakeBackendAuth,
multi: true
};
// http://jasonwatmore.com/post/2017/12/15/angular-5-mock-backend-example-for-backendless-development
import { Injectable } from '@angular/core';
import { HttpRequest, HTTP_INTERCEPTORS } from '@angular/common/http';
import { LoggerService } from 'src/libs/logger/src/logger.module';
import { FakeBackendInterceptorBase } from 'src/app/fake-backends/fake-backend-base';
import { getApiPathFromId } from 'src/app/utils/utils';
@Injectable()
export class FakeBackendInterceptor extends FakeBackendInterceptorBase {
API_ID = ['DUMMY-S3'];
PATH = this.API_ID.map(id => getApiPathFromId(id));
constructor(protected logger: LoggerService) {
super(logger);
}
responseBodyBulider(request: HttpRequest<any>) {
if (this.PATH.some(path => request.url.endsWith(path)) && request.method === 'HEAD') {
if (Math.random() > 0.9) {
return {
status: 200, // 1/10の確率でファイルができたことにするレスポンスをかえす
body: '',
url: this.PATH[0] // ポーリング処理は返り値のURLをそのまま利用するため、urlふくめたダミーレスポンスにする
};
}
} else if (this.PATH.some(path => request.url.endsWith(path)) && request.method === 'GET') {
// 実際のファイルダウンロード。こちらはfack-backendsではつくらない。
}
}
}
export let DUMMY_S3FakeBackendProvider = {
// use fake backend in place of Http service for backend-less development
provide: HTTP_INTERCEPTORS,
useClass: FakeBackendInterceptor,
multi: true
};
// http://jasonwatmore.com/post/2017/12/15/angular-5-mock-backend-example-for-backendless-development
import { Injectable } from '@angular/core';
import { HttpRequest, HttpResponse, HttpHandler, HttpInterceptor, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { LoggerService } from 'src/libs/logger/src/logger.module';
export interface DummyResponse {
status: number;
body: any;
url?: string;
}
@Injectable()
export abstract class FakeBackendInterceptorBase implements HttpInterceptor {
PATH: string | string[];
API_ID: string | string[];
constructor(protected logger: LoggerService) {}
intercept(request: HttpRequest<any>, next: HttpHandler) {
// wrap in delayed observable to simulate server api call
return (
Observable.of(null)
.mergeMap(() => {
const res = this.responseBodyBulider(request);
if (res) {
return this.interceptHandler(res, request);
} else {
// pass through any requests not handled above
return next.handle(request);
}
})
// call materialize and dematerialize to ensure delay even if an error is thrown
// (https://github.com/Reactive-Extensions/RxJS/issues/648)
.materialize()
.delay(50)
.dematerialize()
);
}
abstract responseBodyBulider(request: HttpRequest<any>): DummyResponse | null;
interceptHandler(res: DummyResponse, request: HttpRequest<any>) {
const headers = new HttpHeaders({
'Content-Type': 'application/json; charset=utf-8',
'WWW-Authenticate': ':Bearer dummyToken'
});
if (request.method === 'GET') {
headers.append('ETag', '201711122209010');
}
const fakeRes = new HttpResponse({
status: res.status,
body: res.body,
url: res.url ? res.url : null,
headers: headers
});
this.logger.info('FakeBackend', 'fake response returned', fakeRes);
return Observable.of(fakeRes);
}
}
import { NgModule, ModuleWithProviders } from '@angular/core';
import { CommonModule } from '@angular/common';
import { cmnAuthFakeBackendProvider } from './auth';
import { DUMMY_S3FakeBackendProvider } from './DUMMY-S3';
@NgModule({
imports: [CommonModule],
declarations: []
})
export class FakeBackendsModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: FakeBackendsModule,
providers: [
DUMMY_S3FakeBackendProvider,
cmnAuthFakeBackendProvider,
]
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment