Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

API Docs for the new provideHttpClient #47901

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 11 additions & 11 deletions goldens/public-api/common/http/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1728,15 +1728,15 @@ export enum HttpEventType {
User = 5
}

// @public (undocumented)
// @public
export interface HttpFeature<KindT extends HttpFeatureKind> {
// (undocumented)
傻kind: KindT;
// (undocumented)
傻providers: Provider[];
}

// @public (undocumented)
// @public
export enum HttpFeatureKind {
// (undocumented)
CustomXsrfConfiguration = 2,
Expand Down Expand Up @@ -2162,25 +2162,25 @@ export class JsonpInterceptor {
static 傻prov: i0.傻傻InjectableDeclaration<JsonpInterceptor>;
}

// @public (undocumented)
// @public
export function provideHttpClient(...features: HttpFeature<HttpFeatureKind>[]): EnvironmentProviders;

// @public (undocumented)
// @public
export function withInterceptors(interceptorFns: HttpInterceptorFn[]): HttpFeature<HttpFeatureKind.Interceptors>;

// @public (undocumented)
export function withJsonpSupport(): HttpFeature<HttpFeatureKind.JsonpSupport>;
// @public
export function withInterceptorsFromDi(): HttpFeature<HttpFeatureKind.LegacyInterceptors>;

// @public (undocumented)
export function withLegacyInterceptors(): HttpFeature<HttpFeatureKind.LegacyInterceptors>;
// @public
export function withJsonpSupport(): HttpFeature<HttpFeatureKind.JsonpSupport>;

// @public (undocumented)
// @public
export function withNoXsrfProtection(): HttpFeature<HttpFeatureKind.NoXsrfProtection>;

// @public (undocumented)
// @public
export function withRequestsMadeViaParent(): HttpFeature<HttpFeatureKind.RequestsMadeViaParent>;

// @public (undocumented)
// @public
export function withXsrfConfiguration({ cookieName, headerName }: {
cookieName?: string;
headerName?: string;
Expand Down
2 changes: 1 addition & 1 deletion packages/common/http/public_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export {HTTP_INTERCEPTORS, HttpInterceptor, HttpInterceptorHandler as 傻HttpInte
export {JsonpClientBackend, JsonpInterceptor} from './src/jsonp';
export {HttpClientJsonpModule, HttpClientModule, HttpClientXsrfModule} from './src/module';
export {HttpParameterCodec, HttpParams, HttpParamsOptions, HttpUrlEncodingCodec} from './src/params';
export {HttpFeature, HttpFeatureKind, provideHttpClient, withJsonpSupport, withLegacyInterceptors, withNoXsrfProtection, withXsrfConfiguration, withInterceptors, withRequestsMadeViaParent} from './src/provider';
export {HttpFeature, HttpFeatureKind, provideHttpClient, withJsonpSupport, withNoXsrfProtection, withXsrfConfiguration, withInterceptors, withInterceptorsFromDi, withRequestsMadeViaParent} from './src/provider';
export {HttpRequest} from './src/request';
export {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpProgressEvent, HttpResponse, HttpResponseBase, HttpSentEvent, HttpStatusCode, HttpUploadProgressEvent, HttpUserEvent} from './src/response';
export {HttpXhrBackend} from './src/xhr';
Expand Down
4 changes: 4 additions & 0 deletions packages/common/http/src/interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ export interface HttpInterceptor {
* This function should only be called within the scope of the request that's currently being
* intercepted. Once that request is complete, this downstream handler function should not be
* called.
*
* @publicApi
*
* @see [HTTP Guide](guide/http#intercepting-requests-and-responses)
*/
export type HttpHandlerFn = (req: HttpRequest<unknown>) => Observable<HttpEvent<unknown>>;

Expand Down
4 changes: 2 additions & 2 deletions packages/common/http/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import {ModuleWithProviders, NgModule} from '@angular/core';

import {HTTP_INTERCEPTORS} from './interceptor';
import {provideHttpClient, withJsonpSupport, withLegacyInterceptors, withNoXsrfProtection, withXsrfConfiguration} from './provider';
import {provideHttpClient, withInterceptorsFromDi, withJsonpSupport, withNoXsrfProtection, withXsrfConfiguration} from './provider';
import {HttpXsrfCookieExtractor, HttpXsrfInterceptor, HttpXsrfTokenExtractor, XSRF_DEFAULT_COOKIE_NAME, XSRF_DEFAULT_HEADER_NAME, XSRF_ENABLED} from './xsrf';

/**
Expand Down Expand Up @@ -84,7 +84,7 @@ export class HttpClientXsrfModule {
*/
providers: [
provideHttpClient(
withLegacyInterceptors(),
withInterceptorsFromDi(),
withXsrfConfiguration({
cookieName: XSRF_DEFAULT_COOKIE_NAME,
headerName: XSRF_DEFAULT_HEADER_NAME,
Expand Down
83 changes: 81 additions & 2 deletions packages/common/http/src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ import {jsonpCallbackContext, JsonpCallbackContext, JsonpClientBackend, jsonpInt
import {HttpXhrBackend} from './xhr';
import {HttpXsrfCookieExtractor, HttpXsrfTokenExtractor, XSRF_COOKIE_NAME, XSRF_ENABLED, XSRF_HEADER_NAME, xsrfInterceptorFn} from './xsrf';

/**
* Identifies a particular kind of `HttpFeature`.
*
* @publicApi
*/
export enum HttpFeatureKind {
Interceptors,
LegacyInterceptors,
Expand All @@ -24,6 +29,11 @@ export enum HttpFeatureKind {
RequestsMadeViaParent,
}

/**
* A feature for use when configuring `provideHttpClient`.
*
* @publicApi
*/
export interface HttpFeature<KindT extends HttpFeatureKind> {
傻kind: KindT;
傻providers: Provider[];
Expand All @@ -37,7 +47,21 @@ function makeHttpFeature<KindT extends HttpFeatureKind>(
};
}


/**
* Configures Angular's `HttpClient` service to be available for injection.
*
* By default, `HttpClient` will be configured for injection with its default options for XSRF
* protection of outgoing requests. Additional configuration options can be provided by passing
* feature functions to `provideHttpClient`. For example, HTTP interceptors can be added using the
* `withInterceptors(...)` feature.
*
Comment on lines +56 to +57
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit (not a blocker for this PR): it might be helpful to have a small code snippet to show the structure of the provideHttpClient call (how you would use it with bootstrapApplication call). Since other with* functions refer to this one - it'd be a good location to have an example.

* @see withInterceptors
* @see withInterceptorsFromDi
* @see withXsrfConfiguration
* @see withNoXsrfProtection
* @see withJsonpSupport
* @see withRequestsMadeViaParent
*/
export function provideHttpClient(...features: HttpFeature<HttpFeatureKind>[]):
EnvironmentProviders {
if (ngDevMode) {
Expand Down Expand Up @@ -73,6 +97,14 @@ export function provideHttpClient(...features: HttpFeature<HttpFeatureKind>[]):
return makeEnvironmentProviders(providers);
}

/**
* Adds one or more functional-style HTTP interceptors to the configuration of the `HttpClient`
* instance.
*
* @see HttpInterceptorFn
* @see provideHttpClient
* @publicApi
*/
export function withInterceptors(interceptorFns: HttpInterceptorFn[]):
HttpFeature<HttpFeatureKind.Interceptors> {
return makeHttpFeature(HttpFeatureKind.Interceptors, interceptorFns.map(interceptorFn => {
Expand All @@ -86,7 +118,18 @@ export function withInterceptors(interceptorFns: HttpInterceptorFn[]):

const LEGACY_INTERCEPTOR_FN = new InjectionToken<HttpInterceptorFn>('LEGACY_INTERCEPTOR_FN');

export function withLegacyInterceptors(): HttpFeature<HttpFeatureKind.LegacyInterceptors> {
/**
* Includes class-based interceptors configured using a multi-provider in the current injector into
* the configured `HttpClient` instance.
*
* Prefer `withInterceptors` and functional interceptors instead, as support for DI-provided
* interceptors may be phased out in a later release.
*
* @see HttpInterceptor
* @see HTTP_INTERCEPTORS
* @see provideHttpClient
*/
export function withInterceptorsFromDi(): HttpFeature<HttpFeatureKind.LegacyInterceptors> {
// Note: the legacy interceptor function is provided here via an intermediate token
// (`LEGACY_INTERCEPTOR_FN`), using a pattern which guarantees that if these providers are
// included multiple times, all of the multi-provider entries will have the same instance of the
Expand All @@ -105,6 +148,13 @@ export function withLegacyInterceptors(): HttpFeature<HttpFeatureKind.LegacyInte
]);
}

/**
* Customizes the XSRF protection for the configuration of the current `HttpClient` instance.
*
* This feature is incompatible with the `withNoXsrfProtection` feature.
*
* @see provideHttpClient
*/
export function withXsrfConfiguration(
{cookieName, headerName}: {cookieName?: string, headerName?: string}):
HttpFeature<HttpFeatureKind.CustomXsrfConfiguration> {
Expand All @@ -119,6 +169,13 @@ export function withXsrfConfiguration(
return makeHttpFeature(HttpFeatureKind.CustomXsrfConfiguration, providers);
}

/**
* Disables XSRF protection in the configuration of the current `HttpClient` instance.
*
* This feature is incompatible with the `withXsrfConfiguration` feature.
*
* @see provideHttpClient
*/
export function withNoXsrfProtection(): HttpFeature<HttpFeatureKind.NoXsrfProtection> {
return makeHttpFeature(HttpFeatureKind.NoXsrfProtection, [
{
Expand All @@ -128,6 +185,11 @@ export function withNoXsrfProtection(): HttpFeature<HttpFeatureKind.NoXsrfProtec
]);
}

/**
* Add JSONP support to the configuration of the current `HttpClient` instance.
*
* @see provideHttpClient
*/
export function withJsonpSupport(): HttpFeature<HttpFeatureKind.JsonpSupport> {
return makeHttpFeature(HttpFeatureKind.JsonpSupport, [
JsonpClientBackend,
Expand All @@ -137,6 +199,23 @@ export function withJsonpSupport(): HttpFeature<HttpFeatureKind.JsonpSupport> {
}

/**
* Configures the current `HttpClient` instance to make requests via the parent injector's
* `HttpClient` instead of directly.
*
* By default, `provideHttpClient` configures `HttpClient` in its injector to be an independent
* instance. For example, even if `HttpClient` is configured in the parent injector with
* one or more interceptors, they will not intercept requests made via this instance.
*
* With this option enabled, once the request has passed through the current injector's
* interceptors, it will be delegated to the parent injector's `HttpClient` chain instead of
* dispatched directly, and interceptors in the parent configuration will be applied to the request.
*
* If there are several `HttpClient` instances in the injector hierarchy, it's possible for
* `withRequestsMadeViaParent` to be used at multiple levels, which will cause the request to
* "bubble up" until either reaching the root level or an `HttpClient` which was not configured with
* this option.
*
* @see provideHttpClient
* @developerPreview
*/
export function withRequestsMadeViaParent(): HttpFeature<HttpFeatureKind.RequestsMadeViaParent> {
Expand Down
10 changes: 5 additions & 5 deletions packages/common/http/test/provider_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {TestBed} from '@angular/core/testing';
import {EMPTY, Observable} from 'rxjs';

import {HttpInterceptorFn} from '../src/interceptor';
import {provideHttpClient, withInterceptors, withJsonpSupport, withLegacyInterceptors, withNoXsrfProtection, withRequestsMadeViaParent, withXsrfConfiguration} from '../src/provider';
import {provideHttpClient, withInterceptors, withInterceptorsFromDi, withJsonpSupport, withNoXsrfProtection, withRequestsMadeViaParent, withXsrfConfiguration} from '../src/provider';

describe('provideHttp', () => {
beforeEach(() => {
Expand Down Expand Up @@ -62,10 +62,10 @@ describe('provideHttp', () => {
req.flush('');
});

it('withLegacyInterceptors() should enable legacy interceptors', () => {
it('withInterceptorsFromDi() should enable legacy interceptors', () => {
TestBed.configureTestingModule({
providers: [
provideHttpClient(withLegacyInterceptors()),
provideHttpClient(withInterceptorsFromDi()),
provideLegacyInterceptor('alpha'),
provideLegacyInterceptor('beta'),
provideHttpClientTesting(),
Expand Down Expand Up @@ -144,7 +144,7 @@ describe('provideHttp', () => {
withInterceptors([
makeLiteralTagInterceptorFn('functional'),
]),
withLegacyInterceptors(),
withInterceptorsFromDi(),
),
provideHttpClientTesting(),
provideLegacyInterceptor('legacy'),
Expand All @@ -161,7 +161,7 @@ describe('provideHttp', () => {
TestBed.configureTestingModule({
providers: [
provideHttpClient(
withLegacyInterceptors(),
withInterceptorsFromDi(),
withInterceptors([
makeLiteralTagInterceptorFn('functional'),
]),
Expand Down