From 5448b09f07fd818f09cbc564b2d73a19326fb86f Mon Sep 17 00:00:00 2001 From: rorticus Date: Tue, 1 Aug 2017 13:29:29 -0400 Subject: [PATCH] Adding a flag to disable automatic inclusion of x-requested-with (#350) * Adding a flag to disable automatic inclusion of the x-requested-with header, issue #328 * Documenting request options * Busting IE cache for failed test, issue #328 --- src/request/interfaces.d.ts | 25 ++++++++++++ src/request/providers/node.ts | 73 ++++++++++++++++++++++++++++++++++- src/request/providers/xhr.ts | 11 +++++- tests/unit/request/xhr.ts | 12 ++++++ 4 files changed, 119 insertions(+), 2 deletions(-) diff --git a/src/request/interfaces.d.ts b/src/request/interfaces.d.ts index 8853419b..73e0f3c5 100644 --- a/src/request/interfaces.d.ts +++ b/src/request/interfaces.d.ts @@ -35,14 +35,39 @@ export type Provider = (url: string, options?: RequestOptions) => UploadObservab export type ProviderTest = (url: string, options?: RequestOptions) => boolean | null; export interface RequestOptions { + /** + * Enable cache busting (default false). Cache busting will make a new URL by appending a parameter to the + * requested URL + */ cacheBust?: boolean; credentials?: 'omit' | 'same-origin' | 'include'; + /** + * Body to send along with the http request + */ body?: Blob | BufferSource | FormData | UrlSearchParams | string; + /** + * Headers to send along with the http request + */ headers?: Headers | { [key: string]: string; }; + /** + * HTTP method + */ method?: string; + /** + * Password for HTTP authentication + */ password?: string; + /** + * Number of milliseconds before the request times out and is canceled + */ timeout?: number; + /** + * User for HTTP authentication + */ user?: string; + /** + * Optional query parameter(s) for the URL. The requested url will have these query parameters appended. + */ query?: string | ParamList; } diff --git a/src/request/providers/node.ts b/src/request/providers/node.ts index 17364672..07c9f70a 100644 --- a/src/request/providers/node.ts +++ b/src/request/providers/node.ts @@ -18,34 +18,105 @@ import Observable from '../../Observable'; import SubscriptionPool from '../SubscriptionPool'; /** - * Request options specific to a node request + * Request options specific to a node request. For HTTPS options, see + * https://nodejs.org/api/tls.html#tls_tls_connect_options_callback for more details. */ export interface NodeRequestOptions extends RequestOptions { + /** + * User-agent header + */ agent?: any; + /** + * If specified, the request body is read from the stream specified here, rather than from the `body` field. + */ bodyStream?: Readable; + /** + * HTTPS optionally override the trusted CA certificates + */ ca?: any; + /** + * HTTPS optional cert chains in PEM format. One cert chain should be provided per private key. + */ cert?: string; + /** + * HTTPS optional cipher suite specification + */ ciphers?: string; dataEncoding?: string; + /** + * Whether or not to automatically follow redirects (default true) + */ followRedirects?: boolean; + /** + * HTTPS optional private key in PEM format. + */ key?: string; + /** + * Local interface to bind for network connections. + */ localAddress?: string; + /** + * HTTPS optional shared passphrase used for a single private key and/or a PFX. + */ passphrase?: string; + /** + * HTTPS optional PFX or PKCS12 encoded private key and certificate chain. + */ pfx?: any; + /** + * Optional proxy address. If specified, requests will be sent through this url. + */ proxy?: string; + /** + * HTTPS If not false the server will reject any connection which is not authorized with the list of supplied CAs + */ rejectUnauthorized?: boolean; + /** + * HTTPS optional SSL method to use, default is "SSLv23_method" + */ secureProtocol?: string; + /** + * Unix Domain Socket (use one of host:port or socketPath) + */ socketPath?: string; + /** + * Whether or not to add the gzip and deflate accept headers (default true) + */ acceptCompression?: boolean; + /** + * A set of options to set on the HTTP request + */ socketOptions?: { + /** + * Enable/disable keep-alive functionality, and optionally set the initial delay before the first keepalive probe is sent on an idle socket. + */ keepAlive?: number; + /** + * Disables the Nagle algorithm. By default TCP connections use the Nagle algorithm, they buffer data before sending it off. + */ noDelay?: boolean; + /** + * Number of milliseconds before the HTTP request times out + */ timeout?: number; }; + /** + * Stream encoding on incoming HTTP response + */ streamEncoding?: string; + /** + * Options to control redirect follow logic + */ redirectOptions?: { + /** + * The limit to the number of redirects that will be followed (default 15). This is used to prevent infinite + * redirect loops. + */ limit?: number; count?: number; + /** + * Whether or not to keep the original HTTP method during 301 redirects (default false). + */ keepOriginalMethod?: boolean; }; } diff --git a/src/request/providers/xhr.ts b/src/request/providers/xhr.ts index 4d6245aa..3c3f33b4 100644 --- a/src/request/providers/xhr.ts +++ b/src/request/providers/xhr.ts @@ -17,7 +17,15 @@ import SubscriptionPool from '../SubscriptionPool'; * Request options specific to an XHR request */ export interface XhrRequestOptions extends RequestOptions { + /** + * Controls whether or not the request is synchronous (blocks the main thread) or asynchronous (default). + */ blockMainThread?: boolean; + /** + * Controls whether or not the X-Requested-With header is added to the request (default true). Set to false to not + * include the header. + */ + includeRequestedWithHeader?: boolean; } interface RequestData { @@ -270,6 +278,7 @@ export default function xhr(url: string, options: XhrRequestOptions = {}): Uploa let hasContentTypeHeader = false; let hasRequestedWithHeader = false; + const { includeRequestedWithHeader = true } = options; if (options.headers) { const requestHeaders = new Headers(options.headers); @@ -282,7 +291,7 @@ export default function xhr(url: string, options: XhrRequestOptions = {}): Uploa }); } - if (!hasRequestedWithHeader) { + if (!hasRequestedWithHeader && includeRequestedWithHeader) { request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); } diff --git a/tests/unit/request/xhr.ts b/tests/unit/request/xhr.ts index c0172172..a0d25701 100644 --- a/tests/unit/request/xhr.ts +++ b/tests/unit/request/xhr.ts @@ -403,6 +403,18 @@ registerSuite({ } }); }); + }, + + 'X-Requested-With headers can be disabled'(this: any) { + if (!echoServerAvailable) { + this.skip('No echo server available'); + } + const options = {includeRequestedWithHeader: false}; + return xhrRequest('/__echo/default?norequestedwith', options).then(function (response: any) { + return response.json().then((data: any) => { + assert.isUndefined(data.headers['x-requested-with']); + }); + }); } } },