123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- 'use strict';
- const {PassThrough} = require('stream');
- const duplexer3 = require('duplexer3');
- const requestAsEventEmitter = require('./request-as-event-emitter');
- const {HTTPError, ReadError} = require('./errors');
-
- module.exports = options => {
- const input = new PassThrough();
- const output = new PassThrough();
- const proxy = duplexer3(input, output);
- const piped = new Set();
- let isFinished = false;
-
- options.retry.retries = () => 0;
-
- if (options.body) {
- proxy.write = () => {
- throw new Error('Got\'s stream is not writable when the `body` option is used');
- };
- }
-
- const emitter = requestAsEventEmitter(options, input);
-
- // Cancels the request
- proxy._destroy = emitter.abort;
-
- emitter.on('response', response => {
- const {statusCode} = response;
-
- response.on('error', error => {
- proxy.emit('error', new ReadError(error, options));
- });
-
- if (options.throwHttpErrors && statusCode !== 304 && (statusCode < 200 || statusCode > 299)) {
- proxy.emit('error', new HTTPError(response, options), null, response);
- return;
- }
-
- isFinished = true;
-
- response.pipe(output);
-
- for (const destination of piped) {
- if (destination.headersSent) {
- continue;
- }
-
- for (const [key, value] of Object.entries(response.headers)) {
- // Got gives *decompressed* data. Overriding `content-encoding` header would result in an error.
- // It's not possible to decompress already decompressed data, is it?
- const allowed = options.decompress ? key !== 'content-encoding' : true;
- if (allowed) {
- destination.setHeader(key, value);
- }
- }
-
- destination.statusCode = response.statusCode;
- }
-
- proxy.emit('response', response);
- });
-
- [
- 'error',
- 'request',
- 'redirect',
- 'uploadProgress',
- 'downloadProgress'
- ].forEach(event => emitter.on(event, (...args) => proxy.emit(event, ...args)));
-
- const pipe = proxy.pipe.bind(proxy);
- const unpipe = proxy.unpipe.bind(proxy);
- proxy.pipe = (destination, options) => {
- if (isFinished) {
- throw new Error('Failed to pipe. The response has been emitted already.');
- }
-
- const result = pipe(destination, options);
-
- if (Reflect.has(destination, 'setHeader')) {
- piped.add(destination);
- }
-
- return result;
- };
-
- proxy.unpipe = stream => {
- piped.delete(stream);
- return unpipe(stream);
- };
-
- return proxy;
- };
|