feat(common): two missing features in HttpClient (#17996)
- Add params to HttpRequest API - Add optional description to testing APIs
This commit is contained in:

committed by
Jason Aden

parent
37797e2b4e
commit
c81ad9d19d
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import {HttpHeaders} from './headers';
|
||||
import {HttpParams} from './params';
|
||||
|
||||
/**
|
||||
* Construction interface for `HttpRequest`s.
|
||||
@ -14,7 +15,7 @@ import {HttpHeaders} from './headers';
|
||||
* All values are optional and will override default values if provided.
|
||||
*/
|
||||
interface HttpRequestInit {
|
||||
headers?: HttpHeaders, reportProgress?: boolean,
|
||||
headers?: HttpHeaders, reportProgress?: boolean, params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text', withCredentials?: boolean,
|
||||
}
|
||||
|
||||
@ -61,10 +62,6 @@ function isFormData(value: any): value is FormData {
|
||||
return typeof FormData !== 'undefined' && value instanceof FormData;
|
||||
}
|
||||
|
||||
function isUrlEncodedBody(value: any): value is Object {
|
||||
return typeof value === 'object' && value['__HttpUrlEncodedBody'];
|
||||
}
|
||||
|
||||
/**
|
||||
* An outgoing HTTP request with an optional typed body.
|
||||
*
|
||||
@ -116,34 +113,49 @@ export class HttpRequest<T> {
|
||||
*/
|
||||
readonly method: string;
|
||||
|
||||
/**
|
||||
* Outgoing URL parameters.
|
||||
*/
|
||||
readonly params: HttpParams;
|
||||
|
||||
/**
|
||||
* The outgoing URL with all URL parameters set.
|
||||
*/
|
||||
readonly urlWithParams: string;
|
||||
|
||||
constructor(method: 'DELETE'|'GET'|'HEAD'|'JSONP'|'OPTIONS', url: string, init?: {
|
||||
headers?: HttpHeaders,
|
||||
reportProgress?: boolean,
|
||||
params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text',
|
||||
withCredentials?: boolean,
|
||||
});
|
||||
constructor(method: 'POST'|'PUT'|'PATCH', url: string, body: T|null, init?: {
|
||||
headers?: HttpHeaders,
|
||||
reportProgress?: boolean,
|
||||
params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text',
|
||||
withCredentials?: boolean,
|
||||
});
|
||||
constructor(method: string, url: string, body: T|null, init?: {
|
||||
headers?: HttpHeaders,
|
||||
reportProgress?: boolean,
|
||||
params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text',
|
||||
withCredentials?: boolean,
|
||||
});
|
||||
constructor(
|
||||
method: string, public url: string, third?: T|{
|
||||
method: string, readonly url: string, third?: T|{
|
||||
headers?: HttpHeaders,
|
||||
reportProgress?: boolean,
|
||||
params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text',
|
||||
withCredentials?: boolean,
|
||||
}|null,
|
||||
fourth?: {
|
||||
headers?: HttpHeaders,
|
||||
reportProgress?: boolean,
|
||||
params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text',
|
||||
withCredentials?: boolean,
|
||||
}) {
|
||||
@ -178,12 +190,41 @@ export class HttpRequest<T> {
|
||||
if (!!options.headers) {
|
||||
this.headers = options.headers;
|
||||
}
|
||||
|
||||
if (!!options.params) {
|
||||
this.params = options.params;
|
||||
}
|
||||
}
|
||||
|
||||
// If no headers have been passed in, construct a new HttpHeaders instance.
|
||||
if (!this.headers) {
|
||||
this.headers = new HttpHeaders();
|
||||
}
|
||||
|
||||
// If no parameters have been passed in, construct a new HttpUrlEncodedParams instance.
|
||||
if (!this.params) {
|
||||
this.params = new HttpParams();
|
||||
this.urlWithParams = url;
|
||||
} else {
|
||||
// Encode the parameters to a string in preparation for inclusion in the URL.
|
||||
const params = this.params.toString();
|
||||
if (params.length === 0) {
|
||||
// No parameters, the visible URL is just the URL given at creation time.
|
||||
this.urlWithParams = url;
|
||||
} else {
|
||||
// Does the URL already have query parameters? Look for '?'.
|
||||
const qIdx = url.indexOf('?');
|
||||
// There are 3 cases to handle:
|
||||
// 1) No existing parameters -> append '?' followed by params.
|
||||
// 2) '?' exists and is followed by existing query string ->
|
||||
// append '&' followed by params.
|
||||
// 3) '?' exists at the end of the url -> append params directly.
|
||||
// This basically amounts to determining the character, if any, with
|
||||
// which to join the URL and parameters.
|
||||
const sep: string = qIdx === -1 ? '?' : (qIdx < url.length - 1 ? '&' : '');
|
||||
this.urlWithParams = url + sep + params;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,9 +242,8 @@ export class HttpRequest<T> {
|
||||
typeof this.body === 'string') {
|
||||
return this.body;
|
||||
}
|
||||
// Check whether the body is an instance of HttpUrlEncodedBody, avoiding any direct
|
||||
// references to the class in order to permit it being tree-shaken.
|
||||
if (isUrlEncodedBody(this.body)) {
|
||||
// Check whether the body is an instance of HttpUrlEncodedParams.
|
||||
if (this.body instanceof HttpParams) {
|
||||
return this.body.toString();
|
||||
}
|
||||
// Check whether the body is an object or array, and serialize with JSON if so.
|
||||
@ -244,9 +284,8 @@ export class HttpRequest<T> {
|
||||
if (typeof this.body === 'string') {
|
||||
return 'text/plain';
|
||||
}
|
||||
// `HttpUrlEncodedBody` is detected specially so as to allow it to be
|
||||
// tree-shaken.
|
||||
if (isUrlEncodedBody(this.body)) {
|
||||
// `HttpUrlEncodedParams` has its own content-type.
|
||||
if (this.body instanceof HttpParams) {
|
||||
return 'application/x-www-form-urlencoded;charset=UTF-8';
|
||||
}
|
||||
// Arrays, objects, and numbers will be encoded as JSON.
|
||||
@ -262,28 +301,38 @@ export class HttpRequest<T> {
|
||||
clone(update: {
|
||||
headers?: HttpHeaders,
|
||||
reportProgress?: boolean,
|
||||
params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text',
|
||||
withCredentials?: boolean,
|
||||
body?: T|null,
|
||||
method?: string,
|
||||
url?: string,
|
||||
setHeaders?: {[name: string]: string | string[]},
|
||||
setParams?: {[param: string]: string},
|
||||
}): HttpRequest<T>;
|
||||
clone<V>(update: {
|
||||
headers?: HttpHeaders,
|
||||
reportProgress?: boolean,
|
||||
params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text',
|
||||
withCredentials?: boolean,
|
||||
body?: V|null,
|
||||
method?: string,
|
||||
url?: string,
|
||||
setHeaders?: {[name: string]: string | string[]},
|
||||
setParams?: {[param: string]: string},
|
||||
}): HttpRequest<V>;
|
||||
clone(update: {
|
||||
headers?: HttpHeaders,
|
||||
reportProgress?: boolean,
|
||||
params?: HttpParams,
|
||||
responseType?: 'arraybuffer'|'blob'|'json'|'text',
|
||||
withCredentials?: boolean,
|
||||
body?: any|null,
|
||||
method?: string,
|
||||
url?: string,
|
||||
setHeaders?: {[name: string]: string | string[]},
|
||||
setParams?: {[param: string]: string};
|
||||
} = {}): HttpRequest<any> {
|
||||
// For method, url, and responseType, take the current value unless
|
||||
// it is overridden in the update hash.
|
||||
@ -304,9 +353,10 @@ export class HttpRequest<T> {
|
||||
const reportProgress =
|
||||
(update.reportProgress !== undefined) ? update.reportProgress : this.reportProgress;
|
||||
|
||||
// Headers may need to be cloned later if they're sealed, but being
|
||||
// appended to.
|
||||
// Headers and params may be appended to if `setHeaders` or
|
||||
// `setParams` are used.
|
||||
let headers = update.headers || this.headers;
|
||||
let params = update.params || this.params;
|
||||
|
||||
// Check whether the caller has asked to add headers.
|
||||
if (update.setHeaders !== undefined) {
|
||||
@ -316,10 +366,17 @@ export class HttpRequest<T> {
|
||||
.reduce((headers, name) => headers.set(name, update.setHeaders ![name]), headers);
|
||||
}
|
||||
|
||||
// Check whether the caller has asked to set params.
|
||||
if (update.setParams) {
|
||||
// Set every requested param.
|
||||
params = Object.keys(update.setParams)
|
||||
.reduce((params, param) => params.set(param, update.setParams ![param]), params);
|
||||
}
|
||||
|
||||
// Finally, construct the new HttpRequest using the pieces from above.
|
||||
return new HttpRequest(
|
||||
method, url, body, {
|
||||
headers, reportProgress, responseType, withCredentials,
|
||||
params, headers, reportProgress, responseType, withCredentials,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user