Adding ServerTransferStateModule for AU with custom http interceptor for cache transfer.

This commit is contained in:
softsimon 2020-11-27 18:41:57 +07:00
parent 5248fadcea
commit d0da875e69
No known key found for this signature in database
GPG Key ID: 488D7DCFB5A430D7
4 changed files with 71 additions and 9 deletions

View File

@ -1,6 +1,6 @@
import { BrowserModule } from '@angular/platform-browser';
import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
@ -48,6 +48,7 @@ import { faAngleDoubleDown, faAngleDoubleUp, faAngleDown, faAngleUp, faBolt, faC
import { ApiDocsComponent } from './components/api-docs/api-docs.component';
import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component';
import { StorageService } from './services/storage.service';
import { HttpCacheInterceptor } from './services/http-cache.interceptor';
@NgModule({
declarations: [
@ -85,6 +86,7 @@ import { StorageService } from './services/storage.service';
],
imports: [
BrowserModule.withServerTransition({ appId: 'serverApp' }),
BrowserTransferStateModule,
AppRoutingModule,
HttpClientModule,
BrowserAnimationsModule,
@ -100,6 +102,7 @@ import { StorageService } from './services/storage.service';
AudioService,
SeoService,
StorageService,
{ provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true }
],
bootstrap: [AppComponent]
})

View File

@ -1,13 +1,19 @@
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { ServerModule, ServerTransferStateModule } from '@angular/platform-server';
import { AppModule } from './app.module';
import { AppComponent } from './components/app/app.component';
import { HttpCacheInterceptor } from './services/http-cache.interceptor';
@NgModule({
imports: [
AppModule,
ServerModule,
ServerTransferStateModule,
],
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true }
],
bootstrap: [AppComponent],
})

View File

@ -0,0 +1,42 @@
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
import { HttpInterceptor, HttpEvent, HttpRequest, HttpHandler, HttpResponse } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { tap } from 'rxjs/operators';
import { TransferState, makeStateKey } from '@angular/platform-browser';
import { isPlatformBrowser } from '@angular/common';
@Injectable()
export class HttpCacheInterceptor implements HttpInterceptor {
isBrowser: boolean = isPlatformBrowser(this.platformId);
constructor(
private transferState: TransferState,
@Inject(PLATFORM_ID) private platformId: any,
) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (this.isBrowser && request.method === 'GET') {
const cachedResponse = this.transferState.get(makeStateKey(request.url), null);
if (cachedResponse) {
const modifiedResponse = new HttpResponse<any>({
headers: cachedResponse.headers,
body: cachedResponse.body,
status: cachedResponse.status,
statusText: cachedResponse.statusText,
url: cachedResponse.url
});
this.transferState.remove(makeStateKey(request.url));
return of(modifiedResponse);
}
}
return next.handle(request)
.pipe(tap((event: HttpEvent<any>) => {
if (!this.isBrowser && event instanceof HttpResponse) {
const keyId = request.url.split('/').slice(3).join('/');
this.transferState.set(makeStateKey('/' + keyId), event);
}
}));
}
}

View File

@ -6,12 +6,14 @@ import { Block, Transaction } from '../interfaces/electrs.interface';
import { Subscription } from 'rxjs';
import { ApiService } from './api.service';
import { take } from 'rxjs/operators';
import { TransferState, makeStateKey } from '@angular/platform-browser';
const OFFLINE_RETRY_AFTER_MS = 10000;
const OFFLINE_PING_CHECK_AFTER_MS = 30000;
const EXPECT_PING_RESPONSE_AFTER_MS = 4000;
const initData = makeStateKey('/api/v1/init-data');
@Injectable({
providedIn: 'root'
})
@ -32,6 +34,7 @@ export class WebsocketService {
constructor(
private stateService: StateService,
private apiService: ApiService,
private transferState: TransferState,
) {
if (!this.stateService.isBrowser) {
// @ts-ignore
@ -40,11 +43,17 @@ export class WebsocketService {
this.apiService.getInitData$()
.pipe(take(1))
.subscribe((response) => this.handleResponse(response));
} else {
this.network = this.stateService.network === 'bisq' && !this.stateService.env.BISQ_SEPARATE_BACKEND ? '' : this.stateService.network;
this.websocketSubject = webSocket<WebsocketResponse>(this.webSocketUrl.replace('{network}', this.network ? '/' + this.network : ''));
this.startSubscription();
const theInitData = this.transferState.get(initData, null);
if (theInitData) {
this.handleResponse(theInitData.body);
this.startSubscription(false, true);
} else {
this.startSubscription();
}
this.stateService.networkChanged$.subscribe((network) => {
if (network === 'bisq' && !this.stateService.env.BISQ_SEPARATE_BACKEND) {
@ -70,12 +79,14 @@ export class WebsocketService {
}
}
startSubscription(retrying = false) {
this.stateService.isLoadingWebSocket$.next(true);
startSubscription(retrying = false, hasInitData = false) {
if (!hasInitData) {
this.stateService.isLoadingWebSocket$.next(true);
this.websocketSubject.next({'action': 'init'});
}
if (retrying) {
this.stateService.connectionState$.next(1);
}
this.websocketSubject.next({'action': 'init'});
this.subscription = this.websocketSubject
.subscribe((response: WebsocketResponse) => {
this.stateService.isLoadingWebSocket$.next(false);