Comparing version 10.0.0-beta.1 to 10.0.0-beta.2
@@ -1,2 +0,2 @@ | ||
import { NormalizedOptions, CancelableRequest } from './utils/types'; | ||
export default function asPromise(options: NormalizedOptions): CancelableRequest<any>; | ||
import { CancelableRequest, NormalizedOptions } from './utils/types'; | ||
export default function asPromise<T>(options: NormalizedOptions): CancelableRequest<T>; |
@@ -5,7 +5,7 @@ "use strict"; | ||
const getStream = require("get-stream"); | ||
const PCancelable = require("p-cancelable"); | ||
const is_1 = require("@sindresorhus/is"); | ||
const PCancelable = require("p-cancelable"); | ||
const errors_1 = require("./errors"); | ||
const normalize_arguments_1 = require("./normalize-arguments"); | ||
const request_as_event_emitter_1 = require("./request-as-event-emitter"); | ||
const normalize_arguments_1 = require("./normalize-arguments"); | ||
const parseBody = (body, responseType, statusCode) => { | ||
@@ -48,5 +48,4 @@ if (responseType === 'json' && is_1.default.string(body)) { | ||
proxy.emit('response', response); | ||
const streamAsPromise = is_1.default.null_(options.encoding) ? getStream.buffer(response) : getStream(response, { encoding: options.encoding }); | ||
try { | ||
response.body = await streamAsPromise; | ||
response.body = await getStream(response, { encoding: options.encoding }); | ||
} | ||
@@ -75,3 +74,3 @@ catch (error) { | ||
})); | ||
// Remove any further hooks for that request, because we we'll call them anyway. | ||
// Remove any further hooks for that request, because we'll call them anyway. | ||
// The loop continues. We don't want duplicates (asPromise recursion). | ||
@@ -114,3 +113,3 @@ updatedOptions.hooks.afterResponse = options.hooks.afterResponse.slice(0, index); | ||
const error = new errors_1.HTTPError(response, options); | ||
if (emitter.retry(error) === false) { | ||
if (!emitter.retry(error)) { | ||
if (options.throwHttpErrors) { | ||
@@ -117,0 +116,0 @@ emitError(error); |
/// <reference types="node" /> | ||
import { Duplex as DuplexStream } from 'stream'; | ||
import { NormalizedOptions, GotEvents } from './utils/types'; | ||
export declare class ProxyStream extends DuplexStream implements GotEvents<ProxyStream> { | ||
import { GotEvents, NormalizedOptions } from './utils/types'; | ||
export declare class ProxyStream<T = unknown> extends DuplexStream implements GotEvents<ProxyStream<T>> { | ||
isFromCache?: boolean; | ||
} | ||
export default function asStream(options: NormalizedOptions): ProxyStream; | ||
export default function asStream<T>(options: NormalizedOptions): ProxyStream<T>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const stream_1 = require("stream"); | ||
const duplexer3 = require("duplexer3"); | ||
const stream = require("stream"); | ||
const http_1 = require("http"); | ||
const duplexer3 = require("duplexer3"); | ||
const stream_1 = require("stream"); | ||
const errors_1 = require("./errors"); | ||
const request_as_event_emitter_1 = require("./request-as-event-emitter"); | ||
const errors_1 = require("./errors"); | ||
class ProxyStream extends stream_1.Duplex { | ||
constructor() { | ||
super(...arguments); | ||
Object.defineProperty(this, "isFromCache", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
} | ||
} | ||
@@ -11,0 +20,0 @@ exports.ProxyStream = ProxyStream; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const is_1 = require("@sindresorhus/is"); | ||
const errors_1 = require("./errors"); | ||
const retryAfterStatusCodes = new Set([413, 429, 503]); | ||
const isErrorWithResponse = (error) => (error instanceof errors_1.HTTPError || error instanceof errors_1.ParseError || error instanceof errors_1.MaxRedirectsError); | ||
const calculateRetryDelay = ({ attemptCount, retryOptions, error }) => { | ||
var _a; | ||
var _a, _b; | ||
if (attemptCount > retryOptions.limit) { | ||
@@ -12,23 +14,25 @@ return 0; | ||
const hasErrorCode = Reflect.has(error, 'code') && retryOptions.errorCodes.includes(error.code); | ||
const hasStatusCode = Reflect.has(error, 'response') && retryOptions.statusCodes.includes(error.response.statusCode); | ||
const hasStatusCode = isErrorWithResponse(error) && Reflect.has(error, 'response') && retryOptions.statusCodes.includes((_a = error.response) === null || _a === void 0 ? void 0 : _a.statusCode); | ||
if (!hasMethod || (!hasErrorCode && !hasStatusCode)) { | ||
return 0; | ||
} | ||
const { response } = error; | ||
if (response && Reflect.has(response.headers, 'retry-after') && retryAfterStatusCodes.has(response.statusCode)) { | ||
let after = Number(response.headers['retry-after']); | ||
if (is_1.default.nan(after)) { | ||
after = Date.parse(response.headers['retry-after']) - Date.now(); | ||
if (isErrorWithResponse(error)) { | ||
const { response } = error; | ||
if (response && Reflect.has(response.headers, 'retry-after') && retryAfterStatusCodes.has(response.statusCode)) { | ||
let after = Number(response.headers['retry-after']); | ||
if (is_1.default.nan(after)) { | ||
after = Date.parse(response.headers['retry-after']) - Date.now(); | ||
} | ||
else { | ||
after *= 1000; | ||
} | ||
if (after > retryOptions.maxRetryAfter) { | ||
return 0; | ||
} | ||
return after; | ||
} | ||
else { | ||
after *= 1000; | ||
} | ||
if (after > retryOptions.maxRetryAfter) { | ||
if (((_b = response) === null || _b === void 0 ? void 0 : _b.statusCode) === 413) { | ||
return 0; | ||
} | ||
return after; | ||
} | ||
if (((_a = response) === null || _a === void 0 ? void 0 : _a.statusCode) === 413) { | ||
return 0; | ||
} | ||
const noise = Math.random() * 100; | ||
@@ -35,0 +39,0 @@ return ((2 ** (attemptCount - 1)) * 1000) + noise; |
/// <reference types="node" /> | ||
import { Merge } from 'type-fest'; | ||
import { Merge, PartialDeep } from 'type-fest'; | ||
import { ProxyStream } from './as-stream'; | ||
import * as errors from './errors'; | ||
import { Options, Defaults, Response, CancelableRequest, URLOrOptions, HandlerFunction, ExtendedOptions } from './utils/types'; | ||
import { ProxyStream } from './as-stream'; | ||
import { Hooks } from './known-hook-events'; | ||
import { CancelableRequest, ExtendOptions, HandlerFunction, NormalizedDefaults, Options, Response, URLOrOptions } from './utils/types'; | ||
export declare type HTTPAlias = 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete'; | ||
export declare type ReturnStream = (url: string | Options & { | ||
isStream: true; | ||
}, options?: Options & { | ||
isStream: true; | ||
}) => ProxyStream; | ||
export declare type GotReturn = ProxyStream | CancelableRequest<Response>; | ||
declare type OptionsOfDefaultResponseBody = Options & { | ||
export declare type ReturnStream = <T>(url: string | Merge<Options, { | ||
isStream?: true; | ||
}>, options?: Merge<Options, { | ||
isStream?: true; | ||
}>) => ProxyStream<T>; | ||
export declare type GotReturn<T = unknown> = CancelableRequest<T> | ProxyStream<T>; | ||
export declare type OptionsOfDefaultResponseBody = Merge<Options, { | ||
isStream?: false; | ||
resolveBodyOnly?: false; | ||
responseType?: 'default'; | ||
}; | ||
declare type OptionsOfTextResponseBody = Options & { | ||
}>; | ||
declare type OptionsOfTextResponseBody = Merge<Options, { | ||
isStream?: false; | ||
resolveBodyOnly?: false; | ||
responseType: 'text'; | ||
}; | ||
declare type OptionsOfJSONResponseBody = Options & { | ||
}>; | ||
declare type OptionsOfJSONResponseBody = Merge<Options, { | ||
isStream?: false; | ||
resolveBodyOnly?: false; | ||
responseType: 'json'; | ||
}; | ||
declare type OptionsOfBufferResponseBody = Options & { | ||
}>; | ||
declare type OptionsOfBufferResponseBody = Merge<Options, { | ||
isStream?: false; | ||
resolveBodyOnly?: false; | ||
responseType: 'buffer'; | ||
}; | ||
}>; | ||
declare type ResponseBodyOnly = { | ||
@@ -38,19 +37,19 @@ resolveBodyOnly: true; | ||
interface GotFunctions { | ||
(url: string | OptionsOfDefaultResponseBody, options?: OptionsOfDefaultResponseBody): CancelableRequest<Response>; | ||
<T = string>(url: string | OptionsOfDefaultResponseBody, options?: OptionsOfDefaultResponseBody): CancelableRequest<Response<T>>; | ||
(url: string | OptionsOfTextResponseBody, options?: OptionsOfTextResponseBody): CancelableRequest<Response<string>>; | ||
(url: string | OptionsOfJSONResponseBody, options?: OptionsOfJSONResponseBody): CancelableRequest<Response<object>>; | ||
<T>(url: string | OptionsOfJSONResponseBody, options?: OptionsOfJSONResponseBody): CancelableRequest<Response<T>>; | ||
(url: string | OptionsOfBufferResponseBody, options?: OptionsOfBufferResponseBody): CancelableRequest<Response<Buffer>>; | ||
(url: string | OptionsOfDefaultResponseBody & ResponseBodyOnly, options?: OptionsOfDefaultResponseBody & ResponseBodyOnly): CancelableRequest<any>; | ||
(url: string | OptionsOfTextResponseBody & ResponseBodyOnly, options?: OptionsOfTextResponseBody & ResponseBodyOnly): CancelableRequest<string>; | ||
(url: string | OptionsOfJSONResponseBody & ResponseBodyOnly, options?: OptionsOfJSONResponseBody & ResponseBodyOnly): CancelableRequest<object>; | ||
(url: string | OptionsOfBufferResponseBody & ResponseBodyOnly, options?: OptionsOfBufferResponseBody & ResponseBodyOnly): CancelableRequest<Buffer>; | ||
(url: string | Options & { | ||
<T = string>(url: string | Merge<OptionsOfDefaultResponseBody, ResponseBodyOnly>, options?: Merge<OptionsOfDefaultResponseBody, ResponseBodyOnly>): CancelableRequest<T>; | ||
(url: string | Merge<OptionsOfTextResponseBody, ResponseBodyOnly>, options?: Merge<OptionsOfTextResponseBody, ResponseBodyOnly>): CancelableRequest<string>; | ||
<T>(url: string | Merge<OptionsOfJSONResponseBody, ResponseBodyOnly>, options?: Merge<OptionsOfJSONResponseBody, ResponseBodyOnly>): CancelableRequest<T>; | ||
(url: string | Merge<OptionsOfBufferResponseBody, ResponseBodyOnly>, options?: Merge<OptionsOfBufferResponseBody, ResponseBodyOnly>): CancelableRequest<Buffer>; | ||
<T>(url: string | Merge<Options, { | ||
isStream: true; | ||
}, options?: Options & { | ||
}>, options?: Merge<Options, { | ||
isStream: true; | ||
}): ProxyStream; | ||
}>): ProxyStream<T>; | ||
} | ||
export interface Got extends Merge<Record<HTTPAlias, GotFunctions>, GotFunctions> { | ||
export interface Got extends Record<HTTPAlias, GotFunctions>, GotFunctions { | ||
stream: GotStream; | ||
defaults: Defaults | Readonly<Defaults>; | ||
defaults: NormalizedDefaults | Readonly<NormalizedDefaults>; | ||
GotError: typeof errors.GotError; | ||
@@ -66,7 +65,5 @@ CacheError: typeof errors.CacheError; | ||
CancelError: typeof errors.CancelError; | ||
extend(...instancesOrOptions: Array<Got | ExtendedOptions>): Got; | ||
extend(...instancesOrOptions: Array<Got | ExtendOptions>): Got; | ||
mergeInstances(parent: Got, ...instances: Got[]): Got; | ||
mergeOptions<T extends Options>(...sources: T[]): T & { | ||
hooks: Partial<Hooks>; | ||
}; | ||
mergeOptions<T extends PartialDeep<Options>>(...sources: T[]): T; | ||
} | ||
@@ -77,3 +74,5 @@ export interface GotStream extends Record<HTTPAlias, ReturnStream> { | ||
export declare const defaultHandler: HandlerFunction; | ||
declare const create: (defaults: Defaults) => Got; | ||
declare const create: (defaults: NormalizedDefaults & { | ||
_rawHandlers?: HandlerFunction[] | undefined; | ||
}) => Got; | ||
export default create; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const errors = require("./errors"); | ||
const deep_freeze_1 = require("./utils/deep-freeze"); | ||
const as_promise_1 = require("./as-promise"); | ||
const as_stream_1 = require("./as-stream"); | ||
const errors = require("./errors"); | ||
const normalize_arguments_1 = require("./normalize-arguments"); | ||
const deep_freeze_1 = require("./utils/deep-freeze"); | ||
const getPromiseOrStream = (options) => options.isStream ? as_stream_1.default(options) : as_promise_1.default(options); | ||
const isGotInstance = (value) => (Reflect.has(value, 'defaults') && Reflect.has(value.defaults, 'options')); | ||
const aliases = [ | ||
@@ -22,2 +23,3 @@ 'get', | ||
defaults.handlers = defaults.handlers.map(fn => ((options, next) => { | ||
// This will be assigned by assigning result | ||
let root; | ||
@@ -38,3 +40,3 @@ const result = fn(options, newOptions => { | ||
let iteration = 0; | ||
const iterateHandlers = newOptions => { | ||
const iterateHandlers = (newOptions) => { | ||
return defaults.handlers[iteration++](newOptions, | ||
@@ -45,3 +47,2 @@ // @ts-ignore TS doesn't know that it calls `getPromiseOrStream` at the end | ||
try { | ||
// @ts-ignore This handler takes only one parameter. | ||
return iterateHandlers(normalize_arguments_1.normalizeArguments(url, options, defaults)); | ||
@@ -64,3 +65,3 @@ } | ||
for (const value of instancesOrOptions) { | ||
if (Reflect.has(value, 'defaults')) { | ||
if (isGotInstance(value)) { | ||
optionsArray.push(value.defaults.options); | ||
@@ -85,3 +86,3 @@ handlers.push(...value.defaults._rawHandlers); | ||
handlers, | ||
mutableDefaults | ||
mutableDefaults: Boolean(mutableDefaults) | ||
}); | ||
@@ -88,0 +89,0 @@ }; |
import { Timings } from '@szmarczak/http-timer'; | ||
import { Response, NormalizedOptions } from './utils/types'; | ||
import { TimeoutError as TimedOutError } from './utils/timed-out'; | ||
import { ErrorCode, Response, NormalizedOptions } from './utils/types'; | ||
export declare class GotError extends Error { | ||
code?: string; | ||
code?: ErrorCode; | ||
stack: string; | ||
readonly options: NormalizedOptions; | ||
constructor(message: string, error: (Error & { | ||
code?: string; | ||
}) | { | ||
code?: string; | ||
}, options: NormalizedOptions); | ||
constructor(message: string, error: Partial<Error & { | ||
code?: ErrorCode; | ||
}>, options: NormalizedOptions); | ||
} | ||
@@ -13,0 +12,0 @@ export declare class CacheError extends GotError { |
@@ -7,2 +7,20 @@ "use strict"; | ||
super(message); | ||
Object.defineProperty(this, "code", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, "stack", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, "options", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Error.captureStackTrace(this, this.constructor); | ||
@@ -14,4 +32,18 @@ this.name = 'GotError'; | ||
Object.defineProperty(this, 'options', { | ||
// This fails because of TS 3.7.2 useDefineForClassFields | ||
// Ref: https://github.com/microsoft/TypeScript/issues/34972 | ||
enumerable: false, | ||
value: options | ||
}); | ||
// Recover the original stacktrace | ||
if (!is_1.default.undefined(error.stack)) { | ||
const indexOfMessage = this.stack.indexOf(this.message) + this.message.length; | ||
const thisStackTrace = this.stack.slice(indexOfMessage).split('\n').reverse(); | ||
const errorStackTrace = error.stack.slice(error.stack.indexOf(error.message) + error.message.length).split('\n').reverse(); | ||
// Remove duplicated traces | ||
while (errorStackTrace.length !== 0 && errorStackTrace[0] === thisStackTrace[0]) { | ||
thisStackTrace.shift(); | ||
} | ||
this.stack = `${this.stack.slice(0, indexOfMessage)}${thisStackTrace.reverse().join('\n')}${errorStackTrace.reverse().join('\n')}`; | ||
} | ||
} | ||
@@ -44,4 +76,11 @@ } | ||
super(`${error.message} in "${options.url.toString()}"`, error, options); | ||
Object.defineProperty(this, "response", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.name = 'ParseError'; | ||
Object.defineProperty(this, 'response', { | ||
enumerable: false, | ||
value: response | ||
@@ -54,6 +93,12 @@ }); | ||
constructor(response, options) { | ||
const { statusCode, statusMessage } = response; | ||
super(`Response code ${statusCode} (${statusMessage})`, {}, options); | ||
super(`Response code ${response.statusCode} (${response.statusMessage})`, {}, options); | ||
Object.defineProperty(this, "response", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.name = 'HTTPError'; | ||
Object.defineProperty(this, 'response', { | ||
enumerable: false, | ||
value: response | ||
@@ -67,4 +112,11 @@ }); | ||
super(`Redirected ${maxRedirects} times. Aborting.`, {}, options); | ||
Object.defineProperty(this, "response", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.name = 'MaxRedirectsError'; | ||
Object.defineProperty(this, 'response', { | ||
enumerable: false, | ||
value: response | ||
@@ -84,3 +136,15 @@ }); | ||
constructor(error, timings, options) { | ||
super(error.message, { code: 'ETIMEDOUT' }, options); | ||
super(error.message, error, options); | ||
Object.defineProperty(this, "timings", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, "event", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.name = 'TimeoutError'; | ||
@@ -87,0 +151,0 @@ this.event = error.event; |
/// <reference types="node" /> | ||
import EventEmitter = require('events'); | ||
import { IncomingMessage } from 'http'; | ||
import EventEmitter = require('events'); | ||
import { NormalizedOptions } from './utils/types'; | ||
declare const _default: (response: IncomingMessage, options: NormalizedOptions, emitter: EventEmitter) => void; | ||
declare const _default: (response: IncomingMessage, options: NormalizedOptions, emitter: EventEmitter) => Promise<void>; | ||
export default _default; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const stream = require("stream"); | ||
const decompressResponse = require("decompress-response"); | ||
const mimicResponse = require("mimic-response"); | ||
const stream = require("stream"); | ||
const util_1 = require("util"); | ||
const progress_1 = require("./progress"); | ||
exports.default = (response, options, emitter) => { | ||
const pipeline = util_1.promisify(stream.pipeline); | ||
exports.default = async (response, options, emitter) => { | ||
var _a; | ||
const downloadBodySize = Number(response.headers['content-length']) || undefined; | ||
const progressStream = progress_1.downloadProgress(emitter, downloadBodySize); | ||
const progressStream = progress_1.createProgressStream('downloadProgress', emitter, downloadBodySize); | ||
mimicResponse(response, progressStream); | ||
@@ -15,15 +17,8 @@ const newResponse = (options.decompress && | ||
if (!options.decompress && ['gzip', 'deflate', 'br'].includes((_a = response.headers['content-encoding'], (_a !== null && _a !== void 0 ? _a : '')))) { | ||
options.encoding = null; | ||
options.responseType = 'default'; | ||
// @ts-ignore Internal use. | ||
options.encoding = 'buffer'; | ||
} | ||
emitter.emit('response', newResponse); | ||
emitter.emit('downloadProgress', { | ||
percent: 0, | ||
transferred: 0, | ||
total: downloadBodySize | ||
}); | ||
stream.pipeline(response, progressStream, error => { | ||
if (error) { | ||
emitter.emit('error', error); | ||
} | ||
}); | ||
return pipeline(response, progressStream); | ||
}; |
@@ -44,5 +44,7 @@ "use strict"; | ||
hooks: { | ||
init: [], | ||
beforeRequest: [], | ||
beforeRedirect: [], | ||
beforeRetry: [], | ||
beforeError: [], | ||
afterResponse: [] | ||
@@ -49,0 +51,0 @@ }, |
@@ -1,2 +0,2 @@ | ||
import { CancelableRequest, Response, NormalizedOptions, GenericError } from './utils/types'; | ||
import { CancelableRequest, GeneralError, NormalizedOptions, Options, Response } from './utils/types'; | ||
/** | ||
@@ -23,3 +23,3 @@ Called with plain request options, right before their normalization. This is especially useful in conjunction with got.extend() and got.create() when the input needs custom handling. | ||
*/ | ||
export declare type BeforeRetryHook = (options: NormalizedOptions, error?: GenericError, retryCount?: number) => void | Promise<void>; | ||
export declare type BeforeRetryHook = (options: NormalizedOptions, error?: GeneralError, retryCount?: number) => void | Promise<void>; | ||
/** | ||
@@ -30,3 +30,3 @@ Called with an `Error` instance. The error is passed to the hook right before it's thrown. This is especially useful when you want to have more detailed errors. | ||
*/ | ||
export declare type BeforeErrorHook = <ErrorLike extends GenericError>(error: ErrorLike) => Error | Promise<Error>; | ||
export declare type BeforeErrorHook = <ErrorLike extends GeneralError>(error: ErrorLike) => GeneralError | Promise<GeneralError>; | ||
/** | ||
@@ -37,3 +37,3 @@ Called with [response object](https://github.com/sindresorhus/got#response) and a retry function. | ||
*/ | ||
export declare type AfterResponseHook = (response: Response, retryWithMergedOptions: (options: NormalizedOptions) => CancelableRequest<Response>) => Response | CancelableRequest<Response> | Promise<Response | CancelableRequest<Response>>; | ||
export declare type AfterResponseHook = (response: Response, retryWithMergedOptions: (options: Options) => CancelableRequest<Response>) => Response | CancelableRequest<Response> | Promise<Response | CancelableRequest<Response>>; | ||
export declare type HookType = BeforeErrorHook | InitHook | BeforeRequestHook | BeforeRedirectHook | BeforeRetryHook | AfterResponseHook; | ||
@@ -40,0 +40,0 @@ /** |
/// <reference types="node" /> | ||
import https = require('https'); | ||
import { Options, NormalizedOptions, URLOrOptions, Defaults } from './utils/types'; | ||
export declare const preNormalizeArguments: (options: Options, defaults?: NormalizedOptions) => NormalizedOptions; | ||
import { Merge } from 'type-fest'; | ||
import { Defaults, NormalizedOptions, Options, URLOrOptions } from './utils/types'; | ||
export declare const preNormalizeArguments: (options: Options, defaults?: NormalizedOptions | undefined) => NormalizedOptions; | ||
export declare const mergeOptions: (...sources: Options[]) => NormalizedOptions; | ||
export declare const normalizeArguments: (url: URLOrOptions, options?: Options, defaults?: Defaults) => NormalizedOptions; | ||
export declare type NormalizedRequestArguments = https.RequestOptions & { | ||
body: Pick<NormalizedOptions, 'body'>; | ||
export declare const normalizeArguments: (url: URLOrOptions, options?: Options | undefined, defaults?: Defaults | undefined) => NormalizedOptions; | ||
export declare type NormalizedRequestArguments = Merge<https.RequestOptions, { | ||
body?: ReadableStream; | ||
url: Pick<NormalizedOptions, 'url'>; | ||
}; | ||
export declare const normalizeRequestArguments: (options: NormalizedOptions) => Promise<NormalizedRequestArguments>; | ||
}>; | ||
export declare const normalizeRequestArguments: (options: NormalizedOptions) => Promise<Merge<https.RequestOptions, { | ||
body?: ReadableStream<any> | undefined; | ||
url: Pick<NormalizedOptions, "url">; | ||
}>>; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util_1 = require("util"); | ||
const CacheableRequest = require("cacheable-request"); | ||
const http = require("http"); | ||
const https = require("https"); | ||
const cacheable_lookup_1 = require("cacheable-lookup"); | ||
const CacheableRequest = require("cacheable-request"); | ||
const is_1 = require("@sindresorhus/is"); | ||
const lowercaseKeys = require("lowercase-keys"); | ||
const toReadableStream = require("to-readable-stream"); | ||
const options_to_url_1 = require("./utils/options-to-url"); | ||
const is_1 = require("@sindresorhus/is"); | ||
const cacheable_lookup_1 = require("cacheable-lookup"); | ||
const errors_1 = require("./errors"); | ||
const merge_1 = require("./utils/merge"); | ||
const known_hook_events_1 = require("./known-hook-events"); | ||
@@ -18,2 +16,4 @@ const dynamic_require_1 = require("./utils/dynamic-require"); | ||
const is_form_data_1 = require("./utils/is-form-data"); | ||
const merge_1 = require("./utils/merge"); | ||
const options_to_url_1 = require("./utils/options-to-url"); | ||
const supports_brotli_1 = require("./utils/supports-brotli"); | ||
@@ -26,2 +26,3 @@ const nonEnumerableProperties = [ | ||
]; | ||
const isAgentByProtocol = (agent) => is_1.default.object(agent); | ||
exports.preNormalizeArguments = (options, defaults) => { | ||
@@ -106,3 +107,4 @@ var _a; | ||
if (options.retry.maxRetryAfter === undefined) { | ||
options.retry.maxRetryAfter = Math.min(...[options.timeout.request, options.timeout.connect].filter(n => !is_1.default.nullOrUndefined(n))); | ||
// @ts-ignore We assign if it is undefined, so this is correct | ||
options.retry.maxRetryAfter = Math.min(...[options.timeout.request, options.timeout.connect].filter((n) => !is_1.default.nullOrUndefined(n))); | ||
} | ||
@@ -125,3 +127,5 @@ options.retry.methods = [...new Set(options.retry.methods.map(method => method.toUpperCase()))]; | ||
if (options.cache) { | ||
options.cacheableRequest = new CacheableRequest((options, handler) => options.request(options, handler), options.cache); | ||
options.cacheableRequest = new CacheableRequest( | ||
// @ts-ignore Types broke on infer | ||
(requestOptions, handler) => requestOptions.request(requestOptions, handler), options.cache); | ||
} | ||
@@ -134,2 +138,3 @@ // `options.cookieJar` | ||
if (!Reflect.has(setCookie, util_1.promisify.custom)) { | ||
// @ts-ignore TS is dumb. | ||
setCookie = util_1.promisify(setCookie.bind(options.cookieJar)); | ||
@@ -147,2 +152,6 @@ getCookieString = util_1.promisify(getCookieString.bind(options.cookieJar)); | ||
} | ||
// `options.encoding` | ||
if (is_1.default.null_(options.encoding)) { | ||
throw new TypeError('To get a Buffer, set `options.responseType` to `buffer` instead'); | ||
} | ||
return options; | ||
@@ -175,2 +184,3 @@ }; | ||
exports.normalizeArguments = (url, options, defaults) => { | ||
var _a, _b; | ||
// Merge options | ||
@@ -185,3 +195,3 @@ if (typeof url === 'undefined') { | ||
options.url = url; | ||
options = exports.mergeOptions(defaults && defaults.options, options); | ||
options = exports.mergeOptions((_a = (defaults && defaults.options), (_a !== null && _a !== void 0 ? _a : {})), options); | ||
} | ||
@@ -192,3 +202,3 @@ else { | ||
} | ||
options = exports.mergeOptions(defaults && defaults.options, url, options); | ||
options = exports.mergeOptions((_b = (defaults && defaults.options), (_b !== null && _b !== void 0 ? _b : {})), url, options); | ||
} | ||
@@ -214,3 +224,3 @@ // Normalize URL | ||
let prefixUrl = options.prefixUrl; | ||
Object.defineProperty(options, 'prefixUrl', { | ||
Object.defineProperty(normalizedOptions, 'prefixUrl', { | ||
set: (value) => { | ||
@@ -226,5 +236,5 @@ if (!normalizedOptions.url.href.startsWith(value)) { | ||
// Make it possible to remove default headers | ||
for (const [key, value] of Object.entries(options.headers)) { | ||
for (const [key, value] of Object.entries(normalizedOptions.headers)) { | ||
if (is_1.default.undefined(value)) { | ||
delete options.headers[key]; | ||
delete normalizedOptions.headers[key]; | ||
} | ||
@@ -235,3 +245,3 @@ else if (is_1.default.null_(value)) { | ||
} | ||
for (const hook of options.hooks.init) { | ||
for (const hook of normalizedOptions.hooks.init) { | ||
if (is_1.default.asyncFunction(hook)) { | ||
@@ -249,3 +259,2 @@ throw new TypeError('The `init` hook must be a synchronous function'); | ||
options = exports.mergeOptions(options); | ||
let uploadBodySize; | ||
// Serialize body | ||
@@ -266,2 +275,3 @@ const { headers } = options; | ||
if (!Reflect.has(headers, 'content-type')) { | ||
// @ts-ignore TS is dumb. | ||
headers['content-type'] = `multipart/form-data; boundary=${options.body.getBoundary()}`; | ||
@@ -279,2 +289,3 @@ } | ||
if (!Reflect.has(headers, 'content-type')) { | ||
// @ts-ignore TS is dumb. | ||
headers['content-type'] = 'application/x-www-form-urlencoded'; | ||
@@ -286,2 +297,3 @@ } | ||
if (!Reflect.has(headers, 'content-type')) { | ||
// @ts-ignore TS is dumb. | ||
headers['content-type'] = 'application/json'; | ||
@@ -291,10 +303,6 @@ } | ||
} | ||
// Convert buffer to stream to receive upload progress events (#322) | ||
if (is_1.default.buffer(options.body)) { | ||
uploadBodySize = options.body.length; | ||
const uploadBodySize = await get_body_size_1.default(options); | ||
if (!is_1.default.nodeStream(options.body)) { | ||
options.body = toReadableStream(options.body); | ||
} | ||
else { | ||
uploadBodySize = await get_body_size_1.default(options); | ||
} | ||
// See https://tools.ietf.org/html/rfc7230#section-3.3.2 | ||
@@ -312,2 +320,3 @@ // A user agent SHOULD send a Content-Length in a request message when | ||
!is_1.default.undefined(uploadBodySize)) { | ||
// @ts-ignore TS is dumb. | ||
headers['content-length'] = String(uploadBodySize); | ||
@@ -346,3 +355,3 @@ } | ||
} | ||
if (is_1.default.object(options.agent)) { | ||
if (isAgentByProtocol(options.agent)) { | ||
options.agent = options.agent[options.url.protocol.slice(0, -1)] || options.agent; | ||
@@ -349,0 +358,0 @@ } |
/// <reference types="node" /> | ||
import { ClientRequest } from 'http'; | ||
import EventEmitter = require('events'); | ||
import { Transform as TransformStream } from 'stream'; | ||
import EventEmitter = require('events'); | ||
export declare function downloadProgress(emitter: EventEmitter, downloadBodySize?: number): TransformStream; | ||
export declare function uploadProgress(request: ClientRequest, emitter: EventEmitter, uploadBodySize?: number): void; | ||
export declare function createProgressStream(name: 'downloadProgress' | 'uploadProgress', emitter: EventEmitter, totalBytes?: number | string): TransformStream; |
@@ -5,14 +5,17 @@ "use strict"; | ||
const is_1 = require("@sindresorhus/is"); | ||
function downloadProgress(emitter, downloadBodySize) { | ||
let downloadedBytes = 0; | ||
function createProgressStream(name, emitter, totalBytes) { | ||
let transformedBytes = 0; | ||
if (is_1.default.string(totalBytes)) { | ||
totalBytes = Number(totalBytes); | ||
} | ||
const progressStream = new stream_1.Transform({ | ||
transform(chunk, _encoding, callback) { | ||
downloadedBytes += chunk.length; | ||
const percent = downloadBodySize ? downloadedBytes / downloadBodySize : 0; | ||
transformedBytes += chunk.length; | ||
const percent = totalBytes ? transformedBytes / totalBytes : 0; | ||
// Let `flush()` be responsible for emitting the last event | ||
if (percent < 1) { | ||
emitter.emit('downloadProgress', { | ||
emitter.emit(name, { | ||
percent, | ||
transferred: downloadedBytes, | ||
total: downloadBodySize | ||
transferred: transformedBytes, | ||
total: totalBytes | ||
}); | ||
@@ -23,6 +26,6 @@ } | ||
flush(callback) { | ||
emitter.emit('downloadProgress', { | ||
emitter.emit(name, { | ||
percent: 1, | ||
transferred: downloadedBytes, | ||
total: downloadBodySize | ||
transferred: transformedBytes, | ||
total: totalBytes | ||
}); | ||
@@ -32,67 +35,9 @@ callback(); | ||
}); | ||
return progressStream; | ||
} | ||
exports.downloadProgress = downloadProgress; | ||
function uploadProgress(request, emitter, uploadBodySize) { | ||
const uploadEventFrequency = 150; | ||
let uploadedBytes = 0; | ||
let progressInterval; | ||
emitter.emit('uploadProgress', { | ||
emitter.emit(name, { | ||
percent: 0, | ||
transferred: 0, | ||
total: uploadBodySize | ||
total: totalBytes | ||
}); | ||
request.once('error', () => { | ||
clearInterval(progressInterval); | ||
}); | ||
request.once('abort', () => { | ||
clearInterval(progressInterval); | ||
}); | ||
request.once('response', () => { | ||
clearInterval(progressInterval); | ||
emitter.emit('uploadProgress', { | ||
percent: 1, | ||
transferred: uploadedBytes, | ||
total: uploadBodySize | ||
}); | ||
}); | ||
request.once('socket', (socket) => { | ||
const onSocketConnect = () => { | ||
progressInterval = setInterval(() => { | ||
const lastUploadedBytes = uploadedBytes; | ||
/* istanbul ignore next: future versions of Node may not have this property */ | ||
if (!is_1.default.string(request._header)) { | ||
clearInterval(progressInterval); | ||
const url = new URL('https://github.com/sindresorhus/got/issues/new'); | ||
url.searchParams.set('title', '`request._header` is not present'); | ||
url.searchParams.set('body', 'It causes `uploadProgress` to fail.'); | ||
console.warn('`request._header` is not present. Please report this as a bug:\n' + url.href); | ||
return; | ||
} | ||
const headersSize = Buffer.byteLength(request._header); | ||
uploadedBytes = socket.bytesWritten - headersSize; | ||
// Don't emit events with unchanged progress and | ||
// prevent last event from being emitted, because | ||
// it's emitted when `response` is emitted | ||
if (uploadedBytes === lastUploadedBytes || uploadedBytes === uploadBodySize) { | ||
return; | ||
} | ||
emitter.emit('uploadProgress', { | ||
percent: uploadBodySize ? uploadedBytes / uploadBodySize : 0, | ||
transferred: uploadedBytes, | ||
total: uploadBodySize | ||
}); | ||
}, uploadEventFrequency); | ||
}; | ||
/* istanbul ignore next: hard to test */ | ||
if (socket.connecting) { | ||
socket.once('connect', onSocketConnect); | ||
} | ||
else if (socket.writable) { | ||
// The socket is being reused from pool, | ||
// so the connect event will not be emitted | ||
onSocketConnect(); | ||
} | ||
}); | ||
return progressStream; | ||
} | ||
exports.uploadProgress = uploadProgress; | ||
exports.createProgressStream = createProgressStream; |
/// <reference types="node" /> | ||
import EventEmitter = require('events'); | ||
import { ProxyStream } from './as-stream'; | ||
import { GotError } from './errors'; | ||
import { NormalizedOptions } from './utils/types'; | ||
export interface RequestAsEventEmitter extends EventEmitter { | ||
retry: <T extends Error>(error: T) => boolean; | ||
retry: <T extends GotError>(error: T) => boolean; | ||
abort: () => void; | ||
@@ -10,2 +12,2 @@ } | ||
export default _default; | ||
export declare const proxyEvents: (proxy: any, emitter: any) => void; | ||
export declare const proxyEvents: (proxy: EventEmitter | ProxyStream<unknown>, emitter: RequestAsEventEmitter) => void; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const stream = require("stream"); | ||
const CacheableRequest = require("cacheable-request"); | ||
const EventEmitter = require("events"); | ||
const http = require("http"); | ||
const CacheableRequest = require("cacheable-request"); | ||
const stream = require("stream"); | ||
const util_1 = require("util"); | ||
const is_1 = require("@sindresorhus/is"); | ||
const http_timer_1 = require("@szmarczak/http-timer"); | ||
const timed_out_1 = require("./utils/timed-out"); | ||
const calculate_retry_delay_1 = require("./calculate-retry-delay"); | ||
const errors_1 = require("./errors"); | ||
const get_response_1 = require("./get-response"); | ||
const normalize_arguments_1 = require("./normalize-arguments"); | ||
const progress_1 = require("./progress"); | ||
const errors_1 = require("./errors"); | ||
const timed_out_1 = require("./utils/timed-out"); | ||
const url_to_options_1 = require("./utils/url-to-options"); | ||
const setImmediateAsync = () => new Promise(resolve => setImmediate(resolve)); | ||
const pipeline = util_1.promisify(stream.pipeline); | ||
const redirectCodes = new Set([300, 301, 302, 303, 304, 307, 308]); | ||
@@ -23,3 +26,2 @@ exports.default = (options) => { | ||
let currentRequest; | ||
let shouldAbort = false; | ||
const emitError = async (error) => { | ||
@@ -39,3 +41,2 @@ try { | ||
let httpOptions = await normalize_arguments_1.normalizeRequestArguments(options); | ||
let timings; | ||
const handleResponse = async (response) => { | ||
@@ -56,4 +57,4 @@ var _a; | ||
} | ||
const { statusCode } = response; | ||
const typedResponse = response; | ||
const { statusCode } = typedResponse; | ||
// This is intentionally using `||` over `??` so it can also catch empty status message. | ||
@@ -64,3 +65,2 @@ typedResponse.statusMessage = typedResponse.statusMessage || http.STATUS_CODES[statusCode]; | ||
typedResponse.retryCount = retryCount; | ||
typedResponse.timings = timings; | ||
typedResponse.redirectUrls = redirects; | ||
@@ -114,3 +114,3 @@ typedResponse.request = { options }; | ||
} | ||
get_response_1.default(typedResponse, options, emitter); | ||
await get_response_1.default(typedResponse, options, emitter); | ||
} | ||
@@ -121,65 +121,45 @@ catch (error) { | ||
}; | ||
const handleRequest = (request) => { | ||
if (shouldAbort) { | ||
request.abort(); | ||
return; | ||
} | ||
const handleRequest = async (request) => { | ||
// `request.aborted` is a boolean since v11.0.0: https://github.com/nodejs/node/commit/4b00c4fafaa2ae8c41c1f78823c0feb810ae4723#diff-e3bc37430eb078ccbafe3aa3b570c91a | ||
const isAborted = () => typeof request.aborted === 'number' || request.aborted; | ||
currentRequest = request; | ||
// `request.aborted` is a boolean since v11.0.0: https://github.com/nodejs/node/commit/4b00c4fafaa2ae8c41c1f78823c0feb810ae4723#diff-e3bc37430eb078ccbafe3aa3b570c91a | ||
// We need to allow `TimedOutTimeoutError` here, because it `stream.pipeline(…)` aborts it automatically. | ||
const isAborted = () => typeof request.aborted === 'number' || request.aborted === true; | ||
const onError = (error) => { | ||
const isTimedOutError = error instanceof timed_out_1.TimeoutError; | ||
if (!isTimedOutError && isAborted()) { | ||
return; | ||
if (error instanceof timed_out_1.TimeoutError) { | ||
error = new errors_1.TimeoutError(error, request.timings, options); | ||
} | ||
if (isTimedOutError) { | ||
// @ts-ignore TS is dumb. | ||
error = new errors_1.TimeoutError(error, timings, options); | ||
} | ||
else { | ||
error = new errors_1.RequestError(error, options); | ||
} | ||
if (emitter.retry(error) === false) { | ||
if (!emitter.retry(error)) { | ||
emitError(error); | ||
} | ||
}; | ||
const uploadComplete = (error) => { | ||
if (error) { | ||
const attachErrorHandler = () => { | ||
request.once('error', error => { | ||
// We need to allow `TimedOutTimeoutError` here, because `stream.pipeline(…)` aborts the request automatically. | ||
if (isAborted() && !(error instanceof timed_out_1.TimeoutError)) { | ||
return; | ||
} | ||
onError(error); | ||
return; | ||
} | ||
// No need to attach an error handler here, | ||
// as `stream.pipeline(…)` doesn't remove this handler | ||
// to allow stream reuse. | ||
request.emit('upload-complete'); | ||
}); | ||
}; | ||
request.on('error', onError); | ||
timings = http_timer_1.default(request); // TODO: Make `@szmarczak/http-timer` set `request.timings` and `response.timings` | ||
const uploadBodySize = httpOptions.headers['content-length'] ? Number(httpOptions.headers['content-length']) : undefined; | ||
progress_1.uploadProgress(request, emitter, uploadBodySize); | ||
timed_out_1.default(request, options.timeout, options.url); | ||
emitter.emit('request', request); | ||
if (isAborted()) { | ||
return; | ||
} | ||
try { | ||
if (options.method === 'POST' || options.method === 'PUT' || options.method === 'PATCH') { | ||
if (is_1.default.nodeStream(httpOptions.body)) { | ||
// `stream.pipeline(…)` handles `error` for us. | ||
request.removeListener('error', onError); | ||
stream.pipeline( | ||
// @ts-ignore Upgrade `@sindresorhus/is` | ||
httpOptions.body, request, uploadComplete); | ||
} | ||
else { | ||
request.end(httpOptions.body, uploadComplete); | ||
} | ||
} | ||
else { | ||
request.end(uploadComplete); | ||
} | ||
http_timer_1.default(request); | ||
timed_out_1.default(request, options.timeout, options.url); | ||
emitter.emit('request', request); | ||
const uploadStream = progress_1.createProgressStream('uploadProgress', emitter, httpOptions.headers['content-length']); | ||
await pipeline( | ||
// @ts-ignore Cannot assign ReadableStream to ReadableStream | ||
httpOptions.body, uploadStream, request); | ||
attachErrorHandler(); | ||
request.emit('upload-complete'); | ||
} | ||
catch (error) { | ||
emitError(new errors_1.RequestError(error, options)); | ||
if (isAborted() && error.message === 'Premature close') { | ||
// The request was aborted on purpose | ||
return; | ||
} | ||
onError(error); | ||
// Handle future errors | ||
attachErrorHandler(); | ||
} | ||
@@ -193,4 +173,5 @@ }; | ||
}; | ||
// @ts-ignore ResponseLike missing socket field, should be fixed upstream | ||
const cacheRequest = options.cacheableRequest(httpOptions, handleResponse); | ||
cacheRequest.once('error', error => { | ||
cacheRequest.once('error', (error) => { | ||
if (error instanceof CacheableRequest.RequestError) { | ||
@@ -256,10 +237,15 @@ emitError(new errors_1.RequestError(error, options)); | ||
emitter.abort = () => { | ||
emitter.prependListener('request', (request) => { | ||
request.abort(); | ||
}); | ||
if (currentRequest) { | ||
currentRequest.abort(); | ||
} | ||
else { | ||
shouldAbort = true; | ||
} | ||
}; | ||
setImmediate(async () => { | ||
(async () => { | ||
// Promises are executed immediately. | ||
// If there were no `setImmediate` here, | ||
// `promise.json()` would have no effect | ||
// as the request would be sent already. | ||
await setImmediateAsync(); | ||
try { | ||
@@ -275,3 +261,3 @@ for (const hook of options.hooks.beforeRequest) { | ||
} | ||
}); | ||
})(); | ||
return emitter; | ||
@@ -278,0 +264,0 @@ }; |
import { Options } from './types'; | ||
declare const _default: (options: Options) => Promise<number>; | ||
declare const _default: (options: Options) => Promise<number | undefined>; | ||
export default _default; |
@@ -19,2 +19,5 @@ "use strict"; | ||
} | ||
if (is_1.default.buffer(body)) { | ||
return body.length; | ||
} | ||
if (is_form_data_1.default(body)) { | ||
@@ -21,0 +24,0 @@ return util_1.promisify(body.getLength.bind(body))(); |
@@ -1,1 +0,6 @@ | ||
export default function merge<Target extends Record<string, any>, Source extends Record<string, any>>(target: Target, ...sources: Source[]): Target & Source; | ||
import { Merge } from 'type-fest'; | ||
export default function merge<Target extends { | ||
[key: string]: any; | ||
}, Source extends { | ||
[key: string]: any; | ||
}>(target: Target, ...sources: Source[]): Merge<Source, Target>; |
@@ -47,3 +47,3 @@ "use strict"; | ||
if (Reflect.has(options, key)) { | ||
url[key] = options[key]; | ||
url[key] = options[key].toString(); | ||
} | ||
@@ -50,0 +50,0 @@ } |
import { ClientRequest } from 'http'; | ||
import { Delays } from './types'; | ||
import { Delays, ErrorCode } from './types'; | ||
declare const reentry: unique symbol; | ||
@@ -11,3 +11,3 @@ interface TimedOutOptions { | ||
event: string; | ||
code: string; | ||
code: ErrorCode; | ||
constructor(threshold: number, event: string); | ||
@@ -14,0 +14,0 @@ } |
@@ -11,2 +11,14 @@ "use strict"; | ||
this.event = event; | ||
Object.defineProperty(this, "event", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
Object.defineProperty(this, "code", { | ||
enumerable: true, | ||
configurable: true, | ||
writable: true, | ||
value: void 0 | ||
}); | ||
this.name = 'TimeoutError'; | ||
@@ -46,4 +58,4 @@ this.code = 'ETIMEDOUT'; | ||
const timeoutHandler = (delay, event) => { | ||
request.abort(); | ||
request.emit('error', new TimeoutError(delay, event)); | ||
request.abort(); | ||
}; | ||
@@ -56,6 +68,10 @@ const cancelTimeouts = () => { | ||
}; | ||
request.on('error', error => { | ||
request.once('error', error => { | ||
if (error.message !== 'socket hang up') { | ||
cancelTimeouts(); | ||
} | ||
// Save original behavior | ||
if (request.listenerCount('error') === 0) { | ||
throw error; | ||
} | ||
}); | ||
@@ -62,0 +78,0 @@ once(request, 'response', (response) => { |
/// <reference types="node" /> | ||
import http = require('http'); | ||
import https = require('https'); | ||
import Keyv = require('keyv'); | ||
import CacheableRequest = require('cacheable-request'); | ||
import PCancelable = require('p-cancelable'); | ||
import ResponseLike = require('responselike'); | ||
import { Readable as ReadableStream } from 'stream'; | ||
import CacheableLookup from 'cacheable-lookup'; | ||
import { Timings } from '@szmarczak/http-timer'; | ||
import { Except, Merge } from 'type-fest'; | ||
import PCancelable = require('p-cancelable'); | ||
import CacheableRequest = require('cacheable-request'); | ||
import CacheableLookup from 'cacheable-lookup'; | ||
import Keyv = require('keyv'); | ||
import { Timings } from '@szmarczak/http-timer/dist'; | ||
import { GotReturn } from '../create'; | ||
import { GotError, HTTPError, MaxRedirectsError, ParseError } from '../errors'; | ||
import { Hooks } from '../known-hook-events'; | ||
import { GotError, ParseError, HTTPError, MaxRedirectsError } from '../errors'; | ||
import { ProxyStream } from '../as-stream'; | ||
import { URLOptions } from './options-to-url'; | ||
export declare type GenericError = Error | GotError | ParseError | HTTPError | MaxRedirectsError; | ||
export declare type GeneralError = Error | GotError | HTTPError | MaxRedirectsError | ParseError; | ||
export declare type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'HEAD' | 'DELETE' | 'OPTIONS' | 'TRACE' | 'get' | 'post' | 'put' | 'patch' | 'head' | 'delete' | 'options' | 'trace'; | ||
@@ -31,3 +31,3 @@ export declare type ErrorCode = 'ETIMEDOUT' | 'ECONNRESET' | 'EADDRINUSE' | 'ECONNREFUSED' | 'EPIPE' | 'ENOTFOUND' | 'ENETUNREACH' | 'EAI_AGAIN'; | ||
isFromCache?: boolean; | ||
req: http.ClientRequest; | ||
req?: http.ClientRequest; | ||
requestUrl: string; | ||
@@ -40,4 +40,5 @@ retryCount: number; | ||
}; | ||
url: string; | ||
} | ||
export interface ResponseObject extends ResponseLike { | ||
export interface ResponseObject extends Partial<ResponseLike> { | ||
socket: { | ||
@@ -49,16 +50,19 @@ remoteAddress: string; | ||
attemptCount: number; | ||
retryOptions: RetryOptions; | ||
error: GenericError; | ||
retryOptions: Required<RetryOptions>; | ||
error: GotError | HTTPError | MaxRedirectsError | ParseError; | ||
computedValue: number; | ||
} | ||
export declare type RetryFunction = (retryObject: RetryObject) => number; | ||
export declare type HandlerFunction = <T extends ProxyStream | CancelableRequest<Response>>(options: NormalizedOptions, next: (options: NormalizedOptions) => T) => T; | ||
export interface RetryOptions { | ||
limit?: number; | ||
export declare type HandlerFunction = <T extends GotReturn>(options: NormalizedOptions, next: (options: NormalizedOptions) => T) => T; | ||
export interface DefaultRetryOptions { | ||
limit: number; | ||
methods: Method[]; | ||
statusCodes: number[]; | ||
errorCodes: string[]; | ||
calculateDelay?: RetryFunction; | ||
methods?: Method[]; | ||
statusCodes?: number[]; | ||
errorCodes?: string[]; | ||
maxRetryAfter?: number; | ||
} | ||
export interface RetryOptions extends Partial<DefaultRetryOptions> { | ||
retries?: number; | ||
} | ||
export declare type RequestFunction = typeof https.request; | ||
@@ -78,10 +82,28 @@ export interface AgentByProtocol { | ||
} | ||
export declare type Headers = Record<string, string | string[]>; | ||
export declare type Headers = Record<string, string | string[] | undefined>; | ||
interface CookieJar { | ||
getCookieString(url: string, callback: (error: Error, cookieHeader: string) => void): void; | ||
getCookieString(url: string, callback: (error: Error | null, cookieHeader: string) => void): void; | ||
getCookieString(url: string): Promise<string>; | ||
setCookie(rawCookie: string, url: string, callback: (error: Error, result: unknown) => void): void; | ||
setCookie(rawCookie: string, url: string, callback: (error: Error | null, result: unknown) => void): void; | ||
setCookie(rawCookie: string, url: string): Promise<unknown>; | ||
} | ||
export interface Options extends URLOptions { | ||
export interface DefaultOptions { | ||
method: Method; | ||
retry: DefaultRetryOptions | number; | ||
timeout: Delays | number; | ||
headers: Headers; | ||
hooks: Hooks; | ||
decompress: boolean; | ||
throwHttpErrors: boolean; | ||
followRedirect: boolean; | ||
isStream: boolean; | ||
cache: CacheableRequest.StorageAdapter | string | false; | ||
dnsCache: CacheableLookup | Map<string, string> | Keyv | false; | ||
useElectronNet: boolean; | ||
responseType: ResponseType; | ||
resolveBodyOnly: boolean; | ||
maxRedirects: number; | ||
prefixUrl: URL | string; | ||
} | ||
export interface Options extends Partial<Except<DefaultOptions, 'retry'>>, Merge<Except<https.RequestOptions, 'agent' | 'timeout'>, URLOptions> { | ||
url?: URL | string; | ||
@@ -94,5 +116,5 @@ body?: string | Buffer | ReadableStream; | ||
isStream?: boolean; | ||
encoding?: BufferEncoding | null; | ||
encoding?: BufferEncoding; | ||
method?: Method; | ||
retry?: number | RetryOptions; | ||
retry?: RetryOptions | number; | ||
throwHttpErrors?: boolean; | ||
@@ -112,6 +134,10 @@ cookieJar?: CookieJar; | ||
useElectronNet?: boolean; | ||
form?: Record<string, any>; | ||
json?: Record<string, any>; | ||
form?: { | ||
[key: string]: any; | ||
}; | ||
json?: { | ||
[key: string]: any; | ||
}; | ||
context?: { | ||
[key: string]: unknown; | ||
[key: string]: any; | ||
}; | ||
@@ -121,5 +147,5 @@ maxRedirects?: number; | ||
} | ||
export interface NormalizedOptions extends Except<Options, keyof URLOptions> { | ||
export interface NormalizedOptions extends Except<DefaultOptions, 'dnsCache'>, Except<Options, keyof DefaultOptions> { | ||
headers: Headers; | ||
hooks: Hooks; | ||
hooks: Required<Hooks>; | ||
timeout: Delays; | ||
@@ -134,3 +160,3 @@ dnsCache?: CacheableLookup | false; | ||
} | ||
export interface ExtendedOptions extends Options { | ||
export interface ExtendOptions extends Options { | ||
handlers?: HandlerFunction[]; | ||
@@ -140,4 +166,15 @@ mutableDefaults?: boolean; | ||
export interface Defaults { | ||
options: Except<NormalizedOptions, 'url'>; | ||
options: Merge<Options, { | ||
headers: Headers; | ||
hooks: Required<Hooks>; | ||
}>; | ||
handlers: HandlerFunction[]; | ||
mutableDefaults: boolean; | ||
} | ||
export interface NormalizedDefaults { | ||
options: Merge<Options, { | ||
headers: Headers; | ||
hooks: Required<Hooks>; | ||
}>; | ||
handlers: HandlerFunction[]; | ||
_rawHandlers?: HandlerFunction[]; | ||
@@ -158,4 +195,4 @@ mutableDefaults: boolean; | ||
} | ||
export interface CancelableRequest<T extends Response | Response['body']> extends Merge<PCancelable<T>, GotEvents<CancelableRequest<T>>> { | ||
json<TReturnType extends object>(): CancelableRequest<TReturnType>; | ||
export interface CancelableRequest<T extends Response | Response['body']> extends PCancelable<T>, GotEvents<CancelableRequest<T>> { | ||
json<TReturnType>(): CancelableRequest<TReturnType>; | ||
buffer(): CancelableRequest<Buffer>; | ||
@@ -162,0 +199,0 @@ text(): CancelableRequest<string>; |
@@ -7,4 +7,4 @@ /// <reference types="node" /> | ||
host: string; | ||
hash: string; | ||
search: string; | ||
hash: string | null; | ||
search: string | null; | ||
pathname: string; | ||
@@ -11,0 +11,0 @@ href: string; |
{ | ||
"name": "got", | ||
"version": "10.0.0-beta.1", | ||
"version": "10.0.0-beta.2", | ||
"description": "Simplified HTTP requests", | ||
"license": "MIT", | ||
"repository": "sindresorhus/got", | ||
"funding": "https://github.com/sindresorhus/got?sponsor=1", | ||
"main": "dist/source", | ||
@@ -43,3 +44,2 @@ "engines": { | ||
"@types/cacheable-request": "^6.0.1", | ||
"@types/tough-cookie": "^2.3.5", | ||
"cacheable-lookup": "^0.2.1", | ||
@@ -58,6 +58,10 @@ "cacheable-request": "^7.0.0", | ||
"devDependencies": { | ||
"@sindresorhus/tsconfig": "^0.5.0", | ||
"@sindresorhus/tsconfig": "^0.6.0", | ||
"@types/duplexer3": "^0.1.0", | ||
"@types/express": "^4.17.2", | ||
"@types/lolex": "^3.1.1", | ||
"@types/node": "^12.12.8", | ||
"@types/proxyquire": "^1.3.28", | ||
"@types/sinon": "^7.0.13", | ||
"@types/tough-cookie": "^2.3.5", | ||
"@typescript-eslint/eslint-plugin": "^2.7.0", | ||
@@ -71,2 +75,3 @@ "@typescript-eslint/parser": "^2.7.0", | ||
"eslint-config-xo-typescript": "^0.21.0", | ||
"express": "^4.17.1", | ||
"form-data": "^3.0.0", | ||
@@ -73,0 +78,0 @@ "get-port": "^5.0.0", |
@@ -109,2 +109,4 @@ <div align="center"> | ||
**By default, Got will retry on failure. To disable this option, set [`retry`](#retry) to `0`.** | ||
#### got([url], [options]) | ||
@@ -252,8 +254,8 @@ | ||
- `'default'` - if `options.encoding` is `null`, the body will be a Buffer. Otherwise it will be a string unless it's overwritten in a `afterResponse` hook, | ||
- `'text'` - will always give a string, no matter what's the `options.encoding` or if the body is a custom object, | ||
- `'json'` - will always give an object, unless it's invalid JSON - then it will throw. | ||
- `'buffer'` - will always give a Buffer, no matter what's the `options.encoding`. It will throw if the body is a custom object. | ||
- `'default'` - Will give a string unless the body is overwritten in a `afterResponse` hook or if `options.decompress` is set to false - Will give a Buffer if the response is compresssed. | ||
- `'text'` - Will give a string no matter what. | ||
- `'json'` - Will give an object, unless the body is invalid JSON, then it will throw. | ||
- `'buffer'` - Will give a Buffer, ignoring `options.encoding`. It will throw if the body is a custom object. | ||
The promise has `.json()` and `.buffer()` and `.text()` functions which set this option automatically. | ||
The promise has `.json()` and `.buffer()` and `.text()` methods which set this option automatically. | ||
@@ -263,3 +265,7 @@ Example: | ||
```js | ||
const {body} = await got(url).json(); | ||
// This | ||
const body = await got(url).json(); | ||
// is the same as this | ||
const body = await got(url, {responseType: 'json'}); | ||
``` | ||
@@ -303,7 +309,9 @@ | ||
Type: `string | null`<br> | ||
Type: `string`<br> | ||
Default: `'utf8'` | ||
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. If `null`, the body is returned as a [`Buffer`](https://nodejs.org/api/buffer.html) (binary data). | ||
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings) to be used on `setEncoding` of the response data. | ||
To get a [`Buffer`](https://nodejs.org/api/buffer.html), you need to set [`responseType`](#responseType) to `buffer` instead. | ||
###### form | ||
@@ -761,3 +769,3 @@ | ||
If it's not possible to retrieve the body size (can happen when streaming), `total` will be `null`. | ||
If it's not possible to retrieve the body size (can happen when streaming), `total` will be `undefined`. | ||
@@ -1341,3 +1349,3 @@ ```js | ||
(async () => { | ||
const {body} = await got.post('https://httpbin.org/anything', { | ||
const body = await got.post('https://httpbin.org/anything', { | ||
body: { | ||
@@ -1344,0 +1352,0 @@ hello: 'world' |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
152425
14
2209
1654
33
- Removed@types/tough-cookie@^2.3.5
- Removed@types/tough-cookie@2.3.11(transitive)