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
This commit is contained in:
Alex Rickabaugh 2022-09-20 17:04:02 -07:00 committed by Jessica Janiuk
parent 546f9ca299
commit c3ecd8f5c8
3 changed files with 41 additions and 28 deletions

View file

@ -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<any>, next: HttpHandler): Observable<HttpEvent<any>>;
constructor(injector: EnvironmentInjector);
intercept(initialRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>;
// (undocumented)
static ɵfac: i0.ɵɵFactoryDeclaration<JsonpInterceptor, never>;
// (undocumented)

View file

@ -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<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> {
if (req.method === 'JSONP') {
return inject(JsonpClientBackend).handle(req as HttpRequest<never>);
}
// 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<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (req.method === 'JSONP') {
return this.jsonp.handle(req as HttpRequest<never>);
}
// Fall through for normal HTTP requests.
return next.handle(req);
intercept(initialRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return this.injector.runInContext(
() => jsonpInterceptorFn(
initialRequest, downstreamRequest => next.handle(downstreamRequest)));
}
}

View file

@ -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 {