From c3ecd8f5c81bc83d5dcff74a1bc3c0834db6bc37 Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Tue, 20 Sep 2022 17:04:02 -0700 Subject: [PATCH] refactor(http): convert the JSONP interceptor to the functional style (#47502) This commit rewrites the JSONP interceptor to use the functional interceptor style internally, while still maintaining the same public API and behavior. PR Close #47502 --- goldens/public-api/common/http/index.md | 5 +-- packages/common/http/src/jsonp.ts | 45 ++++++++++++++++++++----- packages/common/http/src/module.ts | 19 ++--------- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/goldens/public-api/common/http/index.md b/goldens/public-api/common/http/index.md index bb2853cb1da..a8b0afe6aa8 100644 --- a/goldens/public-api/common/http/index.md +++ b/goldens/public-api/common/http/index.md @@ -4,6 +4,7 @@ ```ts +import { EnvironmentInjector } from '@angular/core'; import * as i0 from '@angular/core'; import { InjectionToken } from '@angular/core'; import { ModuleWithProviders } from '@angular/core'; @@ -2121,8 +2122,8 @@ export class JsonpClientBackend implements HttpBackend { // @public export class JsonpInterceptor { - constructor(jsonp: JsonpClientBackend); - intercept(req: HttpRequest, next: HttpHandler): Observable>; + constructor(injector: EnvironmentInjector); + intercept(initialRequest: HttpRequest, next: HttpHandler): Observable>; // (undocumented) static ɵfac: i0.ɵɵFactoryDeclaration; // (undocumented) diff --git a/packages/common/http/src/jsonp.ts b/packages/common/http/src/jsonp.ts index a24d3babb40..2678a40c4d4 100644 --- a/packages/common/http/src/jsonp.ts +++ b/packages/common/http/src/jsonp.ts @@ -7,10 +7,11 @@ */ import {DOCUMENT} from '@angular/common'; -import {Inject, Injectable} from '@angular/core'; +import {EnvironmentInjector, Inject, inject, Injectable} from '@angular/core'; import {Observable, Observer} from 'rxjs'; import {HttpBackend, HttpHandler} from './backend'; +import {HttpHandlerFn} from './interceptor'; import {HttpRequest} from './request'; import {HttpErrorResponse, HttpEvent, HttpEventType, HttpResponse, HttpStatusCode} from './response'; @@ -51,6 +52,21 @@ export abstract class JsonpCallbackContext { [key: string]: (data: any) => void; } +/** + * Factory function that determines where to store JSONP callbacks. + * + * Ordinarily JSONP callbacks are stored on the `window` object, but this may not exist + * in test environments. In that case, callbacks are stored on an anonymous object instead. + * + * + */ +export function jsonpCallbackContext(): Object { + if (typeof window === 'object') { + return window; + } + return {}; +} + /** * Processes an `HttpRequest` with the JSONP method, * by performing JSONP style requests. @@ -229,6 +245,19 @@ export class JsonpClientBackend implements HttpBackend { } } +/** + * Identifies requests with the method JSONP and shifts them to the `JsonpClientBackend`. + */ +export function jsonpInterceptorFn( + req: HttpRequest, next: HttpHandlerFn): Observable> { + if (req.method === 'JSONP') { + return inject(JsonpClientBackend).handle(req as HttpRequest); + } + + // Fall through for normal HTTP requests. + return next(req); +} + /** * Identifies requests with the method JSONP and * shifts them to the `JsonpClientBackend`. @@ -239,20 +268,18 @@ export class JsonpClientBackend implements HttpBackend { */ @Injectable() export class JsonpInterceptor { - constructor(private jsonp: JsonpClientBackend) {} + constructor(private injector: EnvironmentInjector) {} /** * Identifies and handles a given JSONP request. - * @param req The outgoing request object to handle. + * @param initialRequest The outgoing request object to handle. * @param next The next interceptor in the chain, or the backend * if no interceptors remain in the chain. * @returns An observable of the event stream. */ - intercept(req: HttpRequest, next: HttpHandler): Observable> { - if (req.method === 'JSONP') { - return this.jsonp.handle(req as HttpRequest); - } - // Fall through for normal HTTP requests. - return next.handle(req); + intercept(initialRequest: HttpRequest, next: HttpHandler): Observable> { + return this.injector.runInContext( + () => jsonpInterceptorFn( + initialRequest, downstreamRequest => next.handle(downstreamRequest))); } } diff --git a/packages/common/http/src/module.ts b/packages/common/http/src/module.ts index 28be7a90fb8..9519f6aa75b 100644 --- a/packages/common/http/src/module.ts +++ b/packages/common/http/src/module.ts @@ -11,25 +11,10 @@ import {ModuleWithProviders, NgModule} from '@angular/core'; import {HttpBackend, HttpHandler} from './backend'; import {HttpClient} from './client'; import {HTTP_INTERCEPTOR_FNS, HTTP_INTERCEPTORS, HttpInterceptorHandler, LEGACY_INTERCEPTOR_FN, legacyInterceptorFnFactory, NoopInterceptor} from './interceptor'; -import {JsonpCallbackContext, JsonpClientBackend, JsonpInterceptor} from './jsonp'; +import {jsonpCallbackContext, JsonpCallbackContext, JsonpClientBackend, jsonpInterceptorFn} from './jsonp'; import {HttpXhrBackend} from './xhr'; import {HttpXsrfCookieExtractor, HttpXsrfInterceptor, HttpXsrfTokenExtractor, XSRF_COOKIE_NAME, XSRF_HEADER_NAME} from './xsrf'; -/** - * Factory function that determines where to store JSONP callbacks. - * - * Ordinarily JSONP callbacks are stored on the `window` object, but this may not exist - * in test environments. In that case, callbacks are stored on an anonymous object instead. - * - * - */ -export function jsonpCallbackContext(): Object { - if (typeof window === 'object') { - return window; - } - return {}; -} - /** * Configures XSRF protection support for outgoing requests. * @@ -140,7 +125,7 @@ export class HttpClientModule { providers: [ JsonpClientBackend, {provide: JsonpCallbackContext, useFactory: jsonpCallbackContext}, - {provide: HTTP_INTERCEPTORS, useClass: JsonpInterceptor, multi: true}, + {provide: HTTP_INTERCEPTOR_FNS, useValue: jsonpInterceptorFn, multi: true}, ], }) export class HttpClientJsonpModule {