From 1e20551d2a375a5b2abf602b9ba31edb263a310f Mon Sep 17 00:00:00 2001 From: Yury Bondarenko Date: Fri, 13 Jan 2023 17:54:39 +0100 Subject: [PATCH] Keep SSL sessions alive between xhr2 requests --- src/app/core/services/server-xhr.service.ts | 51 +++++++++++++++++++++ src/modules/app/server-app.module.ts | 6 +++ 2 files changed, 57 insertions(+) create mode 100644 src/app/core/services/server-xhr.service.ts diff --git a/src/app/core/services/server-xhr.service.ts b/src/app/core/services/server-xhr.service.ts new file mode 100644 index 0000000000..17e5162d43 --- /dev/null +++ b/src/app/core/services/server-xhr.service.ts @@ -0,0 +1,51 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ + +import { XhrFactory } from '@angular/common'; +import { Injectable } from '@angular/core'; +import { Agent as HttpAgent, AgentOptions as HttpAgentOptions } from 'http'; +import { Agent as HttpsAgent } from 'https'; +import { XMLHttpRequest } from 'xhr2'; + +/** + * Allow HTTP sessions to be kept alive. + * Without this configuration, Angular re-connects to REST multiple times per SSR cycle. + * https://nodejs.org/api/http.html#new-agentoptions + */ +const agentOptions: HttpAgentOptions = { + keepAlive: true, + keepAliveMsecs: 60 * 1000, +}; + +// Agents need to be reused between requests, otherwise keep-alive doesn't help. +const httpAgent = new HttpAgent(agentOptions); +const httpsAgent = new HttpsAgent(agentOptions); + +/** + * Contructs the XMLHttpRequest instances used for all HttpClient requests. + * Emulated by https://github.com/pwnall/node-xhr2 on the server. + * This class overrides the built-in Angular implementation to set additional configuration. + * + * Note that this must be provided in ServerAppModule; + * it doesn't work when added as a Universal engine provider. + */ +@Injectable() +export class ServerXhrService implements XhrFactory { + build(): XMLHttpRequest { + const xhr = new XMLHttpRequest(); + + // This call is specific to xhr2 and will probably break if we use another library. + // https://github.com/pwnall/node-xhr2#features + (xhr as any).nodejsSet({ + httpAgent, + httpsAgent, + }); + + return xhr; + } +} diff --git a/src/modules/app/server-app.module.ts b/src/modules/app/server-app.module.ts index 01a5548948..6bb344a1cd 100644 --- a/src/modules/app/server-app.module.ts +++ b/src/modules/app/server-app.module.ts @@ -34,6 +34,8 @@ import { AuthRequestService } from '../../app/core/auth/auth-request.service'; import { ServerAuthRequestService } from '../../app/core/auth/server-auth-request.service'; import { CorrelationIdService } from '../../app/correlation-id/correlation-id.service'; import { AppConfig, APP_CONFIG_STATE } from '../../config/app-config.interface'; +import { XhrFactory } from '@angular/common'; +import { ServerXhrService } from '../../app/core/services/server-xhr.service'; import { environment } from '../../environments/environment'; @@ -121,6 +123,10 @@ export function createTranslateLoader() { provide: HardRedirectService, useClass: ServerHardRedirectService, }, + { + provide: XhrFactory, + useClass: ServerXhrService, + }, ] }) export class ServerAppModule {