Skip to content

Instantly share code, notes, and snippets.

@tw3
Last active November 15, 2019 19:00
Show Gist options
  • Save tw3/0debb1a7c9a15cc79fee3338216977c6 to your computer and use it in GitHub Desktop.
Save tw3/0debb1a7c9a15cc79fee3338216977c6 to your computer and use it in GitHub Desktop.
Serializer that stores and pulls a generic configuration object from the HttpHeader instance so as to configure an interceptor on a per-request basis
import { HttpHeaders, HttpRequest } from '@angular/common/http';
import { isNullOrUndefined } from '../../util/misc-util';
import { HttpClientHeaders, HttpClientOptions } from './http-client-options';
/**
* Unfortunately Angular does not provide a way to pass metadata/configs into interceptors so
* we have to do it ourselves.
*
* https://github.com/angular/angular/issues/18155
*/
export interface PullInterceptorConfigResult<T> {
request: HttpRequest<any>; // NOSONAR
config: T | undefined;
}
export class InterceptorRequestConfigSerializer {
static pullConfig<T>(req: HttpRequest<any>, configName: string): PullInterceptorConfigResult<T> { // NOSONAR
return InterceptorRequestHeaderConfigSerializer.pullConfig(req, configName);
}
static setConfig(options: HttpClientOptions, configName: string, config: object): HttpClientOptions | undefined {
return InterceptorRequestHeaderConfigSerializer.setConfig(options, configName, config);
}
}
class InterceptorRequestHeaderConfigSerializer {
private static readonly INTERCEPTOR_HEADER_PROPERTY_PREFIX = '__interceptor-config__';
static pullConfig<T>(req: HttpRequest<any>, configName: string): PullInterceptorConfigResult<T> { // NOSONAR
if (!(req.headers instanceof HttpHeaders)) {
// Not an instance of HttpHeaders -> no config set
return { request: req, config: undefined };
}
const headersInst: HttpHeaders = req.headers;
const headerProperty: string = this.getHeaderProperty(configName);
const config: T = headersInst[headerProperty];
return { request: req, config };
}
static setConfig(options: HttpClientOptions, configName: string, config: object): HttpClientOptions | undefined {
if (isNullOrUndefined(options)) {
return undefined;
}
const headersInst: HttpHeaders = this.getHeadersInstance(options.headers);
const headerProperty: string = this.getHeaderProperty(configName);
headersInst[headerProperty] = config;
return {
...options,
headers: headersInst
};
}
private static getHeadersInstance(inputHeaders: HttpClientHeaders): HttpHeaders {
if (inputHeaders instanceof HttpHeaders) {
return inputHeaders;
}
if (isNullOrUndefined(inputHeaders)) {
return new HttpHeaders();
}
return new HttpHeaders(inputHeaders);
}
private static getHeaderProperty(configName: string): string {
return `${this.INTERCEPTOR_HEADER_PROPERTY_PREFIX}${configName}`;
}
}
// Backup class in case the above class doesn't work
// eslint-disable-next-line @typescript-eslint/no-unused-vars
class InterceptorRequestHeaderConfigSerializer2 {
private static readonly INTERCEPTOR_HEADER_PREFIX = 'X-Interceptor-Headers-';
/**
* Gets the interceptor header and removes it
*/
static pullConfig<T>(req: HttpRequest<any>, configName: string): PullInterceptorConfigResult<T> { // NOSONAR
let headerValue: T;
const headersInst: HttpHeaders = this.getHeadersInstance(req.headers);
const headerKey: string = this.getHeaderKey(configName);
const headerValueStr: string = headersInst.get(headerKey);
if (!isNullOrUndefined(headerValueStr)) {
headerValue = JSON.parse(headerValueStr);
req = req.clone({
headers: req.headers.delete(headerKey)
});
}
return { request: req, config: headerValue };
}
static setConfig(options: HttpClientOptions, configName: string, config: object): HttpClientOptions | undefined {
if (isNullOrUndefined(options)) {
return undefined;
}
const headersInst: HttpHeaders = this.getHeadersInstance(options.headers);
const headerKey: string = this.getHeaderKey(configName);
const headerValueStr: string = JSON.stringify(config);
const newHeadersInst: HttpHeaders = headersInst.set(headerKey, headerValueStr);
return {
...options,
headers: newHeadersInst
};
}
private static getHeadersInstance(inputHeaders: HttpClientHeaders): HttpHeaders {
if (inputHeaders instanceof HttpHeaders) {
return inputHeaders;
}
if (isNullOrUndefined(inputHeaders)) {
return new HttpHeaders();
}
return new HttpHeaders(inputHeaders);
}
private static getHeaderKey(configName: string): string {
return `${this.INTERCEPTOR_HEADER_PREFIX}${configName}`;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment