@whatwg-node/node-fetch 0.4.8 → 0.4.9-rc-20230718150451-79c2199

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cjs/Blob.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PonyfillBlob = void 0;
4
+ /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
4
5
  const ReadableStream_js_1 = require("./ReadableStream.js");
5
6
  const utils_js_1 = require("./utils.js");
6
7
  function getBlobPartAsBuffer(blobPart) {
package/cjs/Headers.js CHANGED
@@ -24,7 +24,7 @@ class PonyfillHeaders {
24
24
  }
25
25
  const normalized = key.toLowerCase();
26
26
  if (Array.isArray(this.headersInit)) {
27
- return this.headersInit.find(header => header[0] === normalized)?.[1] || null;
27
+ return this.headersInit.find(header => header[0].toLowerCase() === normalized)?.[1] || null;
28
28
  }
29
29
  else if (isHeadersLike(this.headersInit)) {
30
30
  return this.headersInit.get(normalized);
package/cjs/fetchCurl.js CHANGED
@@ -1,82 +1,92 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.fetchCurl = void 0;
4
- /* eslint-disable @typescript-eslint/no-this-alias */
5
- const stream_1 = require("stream");
6
- const Headers_js_1 = require("./Headers.js");
4
+ const node_stream_1 = require("node:stream");
7
5
  const Response_js_1 = require("./Response.js");
8
6
  const utils_js_1 = require("./utils.js");
9
- async function fetchCurl(fetchRequest) {
7
+ function fetchCurl(fetchRequest) {
8
+ const { Curl, CurlCode, CurlFeature, CurlPause, CurlProgressFunc } = globalThis['libcurl'];
9
+ const curlHandle = new Curl();
10
+ if (fetchRequest['_signal']) {
11
+ fetchRequest['_signal'].onabort = () => {
12
+ curlHandle.pause(CurlPause.Recv);
13
+ };
14
+ }
15
+ curlHandle.enable(CurlFeature.NoDataParsing);
16
+ curlHandle.setOpt('URL', fetchRequest.url);
17
+ curlHandle.setOpt('SSL_VERIFYPEER', false);
18
+ curlHandle.enable(CurlFeature.StreamResponse);
19
+ curlHandle.setStreamProgressCallback(function () {
20
+ return fetchRequest['_signal']?.aborted
21
+ ? process.env.DEBUG
22
+ ? CurlProgressFunc.Continue
23
+ : 1
24
+ : 0;
25
+ });
10
26
  const nodeReadable = (fetchRequest.body != null
11
27
  ? 'pipe' in fetchRequest.body
12
28
  ? fetchRequest.body
13
- : stream_1.Readable.from(fetchRequest.body)
29
+ : node_stream_1.Readable.from(fetchRequest.body)
14
30
  : null);
31
+ if (nodeReadable) {
32
+ curlHandle.setOpt('UPLOAD', true);
33
+ curlHandle.setUploadStream(nodeReadable);
34
+ }
35
+ if (process.env.DEBUG) {
36
+ curlHandle.setOpt('VERBOSE', true);
37
+ }
38
+ curlHandle.setOpt('TRANSFER_ENCODING', false);
39
+ curlHandle.setOpt('HTTP_TRANSFER_DECODING', true);
40
+ curlHandle.setOpt('FOLLOWLOCATION', fetchRequest.redirect === 'follow');
41
+ curlHandle.setOpt('MAXREDIRS', 20);
42
+ curlHandle.setOpt('ACCEPT_ENCODING', '');
43
+ curlHandle.setOpt('CUSTOMREQUEST', fetchRequest.method);
15
44
  const headersSerializer = fetchRequest.headersSerializer || utils_js_1.defaultHeadersSerializer;
16
45
  let size;
17
- const curlyHeaders = headersSerializer(fetchRequest.headers, value => {
46
+ const curlHeaders = headersSerializer(fetchRequest.headers, value => {
18
47
  size = Number(value);
19
48
  });
20
- let easyNativeBinding;
21
- const curlyOptions = {
22
- sslVerifyPeer: false,
23
- // we want the unparsed binary response to be returned as a stream to us
24
- curlyStreamResponse: true,
25
- curlyResponseBodyParser: false,
26
- curlyProgressCallback() {
27
- if (easyNativeBinding == null) {
28
- easyNativeBinding = this;
29
- }
30
- return fetchRequest['_signal']?.aborted ? 1 : 0;
31
- },
32
- upload: nodeReadable != null,
33
- transferEncoding: false,
34
- httpTransferDecoding: true,
35
- followLocation: fetchRequest.redirect === 'follow',
36
- maxRedirs: 20,
37
- acceptEncoding: '',
38
- curlyStreamUpload: nodeReadable,
39
- // this will just make libcurl use their own progress function (which is pretty neat)
40
- // curlyProgressCallback() { return CurlProgressFunc.Continue },
41
- // verbose: true,
42
- httpHeader: curlyHeaders,
43
- customRequest: fetchRequest.method,
44
- };
45
49
  if (size != null) {
46
- curlyOptions.inFileSize = size;
50
+ curlHandle.setOpt('INFILESIZE', size);
47
51
  }
48
- const { curly, CurlCode, CurlPause } = globalThis['libcurl'];
49
- if (fetchRequest['_signal']) {
50
- fetchRequest['_signal'].onabort = () => {
51
- if (easyNativeBinding != null) {
52
- easyNativeBinding.pause(CurlPause.Recv);
52
+ curlHandle.setOpt('HTTPHEADER', curlHeaders);
53
+ curlHandle.enable(CurlFeature.NoHeaderParsing);
54
+ return new Promise(function promiseResolver(resolve, reject) {
55
+ curlHandle.once('end', function endListener() {
56
+ curlHandle.close();
57
+ });
58
+ curlHandle.once('error', function errorListener(error) {
59
+ if (error.isCurlError && error.code === CurlCode.CURLE_ABORTED_BY_CALLBACK) {
60
+ // this is expected
53
61
  }
54
- };
55
- }
56
- const curlyResult = await curly(fetchRequest.url, curlyOptions);
57
- const responseHeaders = new Headers_js_1.PonyfillHeaders();
58
- curlyResult.headers.forEach(headerInfo => {
59
- for (const key in headerInfo) {
60
- if (key === 'location' || (key === 'Location' && fetchRequest.redirect === 'error')) {
61
- throw new Error('redirects are not allowed');
62
+ else {
63
+ // this is unexpected
64
+ reject(error);
62
65
  }
63
- if (key !== 'result') {
64
- responseHeaders.append(key, headerInfo[key]);
65
- }
66
- }
67
- });
68
- curlyResult.data.on('error', (err) => {
69
- if (err.isCurlError && err.code === CurlCode.CURLE_ABORTED_BY_CALLBACK) {
70
- // this is expected
71
- }
72
- else {
73
- throw err;
74
- }
75
- });
76
- return new Response_js_1.PonyfillResponse(curlyResult.data, {
77
- status: curlyResult.statusCode,
78
- headers: responseHeaders,
79
- url: fetchRequest.url,
66
+ curlHandle.close();
67
+ });
68
+ curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
69
+ const headersFlat = headersBuf
70
+ .toString('utf8')
71
+ .split(/\r?\n|\r/g)
72
+ .filter(headerFilter => {
73
+ if (headerFilter && !headerFilter.startsWith('HTTP/')) {
74
+ if (fetchRequest.redirect === 'error' &&
75
+ (headerFilter.includes('location') || headerFilter.includes('Location'))) {
76
+ reject(new Error('redirect is not allowed'));
77
+ }
78
+ return true;
79
+ }
80
+ return false;
81
+ });
82
+ const headersInit = headersFlat.map(headerFlat => headerFlat.split(/:\s(.+)/).slice(0, 2));
83
+ resolve(new Response_js_1.PonyfillResponse(stream, {
84
+ status,
85
+ headers: headersInit,
86
+ url: fetchRequest.url,
87
+ }));
88
+ });
89
+ curlHandle.perform();
80
90
  });
81
91
  }
82
92
  exports.fetchCurl = fetchCurl;
package/esm/Blob.js CHANGED
@@ -1,3 +1,4 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
1
2
  import { PonyfillReadableStream } from './ReadableStream.js';
2
3
  import { uint8ArrayToArrayBuffer } from './utils.js';
3
4
  function getBlobPartAsBuffer(blobPart) {
package/esm/Headers.js CHANGED
@@ -20,7 +20,7 @@ export class PonyfillHeaders {
20
20
  }
21
21
  const normalized = key.toLowerCase();
22
22
  if (Array.isArray(this.headersInit)) {
23
- return this.headersInit.find(header => header[0] === normalized)?.[1] || null;
23
+ return this.headersInit.find(header => header[0].toLowerCase() === normalized)?.[1] || null;
24
24
  }
25
25
  else if (isHeadersLike(this.headersInit)) {
26
26
  return this.headersInit.get(normalized);
package/esm/fetchCurl.js CHANGED
@@ -1,78 +1,88 @@
1
- /* eslint-disable @typescript-eslint/no-this-alias */
2
- import { Readable } from 'stream';
3
- import { PonyfillHeaders } from './Headers.js';
1
+ import { Readable } from 'node:stream';
4
2
  import { PonyfillResponse } from './Response.js';
5
3
  import { defaultHeadersSerializer } from './utils.js';
6
- export async function fetchCurl(fetchRequest) {
4
+ export function fetchCurl(fetchRequest) {
5
+ const { Curl, CurlCode, CurlFeature, CurlPause, CurlProgressFunc } = globalThis['libcurl'];
6
+ const curlHandle = new Curl();
7
+ if (fetchRequest['_signal']) {
8
+ fetchRequest['_signal'].onabort = () => {
9
+ curlHandle.pause(CurlPause.Recv);
10
+ };
11
+ }
12
+ curlHandle.enable(CurlFeature.NoDataParsing);
13
+ curlHandle.setOpt('URL', fetchRequest.url);
14
+ curlHandle.setOpt('SSL_VERIFYPEER', false);
15
+ curlHandle.enable(CurlFeature.StreamResponse);
16
+ curlHandle.setStreamProgressCallback(function () {
17
+ return fetchRequest['_signal']?.aborted
18
+ ? process.env.DEBUG
19
+ ? CurlProgressFunc.Continue
20
+ : 1
21
+ : 0;
22
+ });
7
23
  const nodeReadable = (fetchRequest.body != null
8
24
  ? 'pipe' in fetchRequest.body
9
25
  ? fetchRequest.body
10
26
  : Readable.from(fetchRequest.body)
11
27
  : null);
28
+ if (nodeReadable) {
29
+ curlHandle.setOpt('UPLOAD', true);
30
+ curlHandle.setUploadStream(nodeReadable);
31
+ }
32
+ if (process.env.DEBUG) {
33
+ curlHandle.setOpt('VERBOSE', true);
34
+ }
35
+ curlHandle.setOpt('TRANSFER_ENCODING', false);
36
+ curlHandle.setOpt('HTTP_TRANSFER_DECODING', true);
37
+ curlHandle.setOpt('FOLLOWLOCATION', fetchRequest.redirect === 'follow');
38
+ curlHandle.setOpt('MAXREDIRS', 20);
39
+ curlHandle.setOpt('ACCEPT_ENCODING', '');
40
+ curlHandle.setOpt('CUSTOMREQUEST', fetchRequest.method);
12
41
  const headersSerializer = fetchRequest.headersSerializer || defaultHeadersSerializer;
13
42
  let size;
14
- const curlyHeaders = headersSerializer(fetchRequest.headers, value => {
43
+ const curlHeaders = headersSerializer(fetchRequest.headers, value => {
15
44
  size = Number(value);
16
45
  });
17
- let easyNativeBinding;
18
- const curlyOptions = {
19
- sslVerifyPeer: false,
20
- // we want the unparsed binary response to be returned as a stream to us
21
- curlyStreamResponse: true,
22
- curlyResponseBodyParser: false,
23
- curlyProgressCallback() {
24
- if (easyNativeBinding == null) {
25
- easyNativeBinding = this;
26
- }
27
- return fetchRequest['_signal']?.aborted ? 1 : 0;
28
- },
29
- upload: nodeReadable != null,
30
- transferEncoding: false,
31
- httpTransferDecoding: true,
32
- followLocation: fetchRequest.redirect === 'follow',
33
- maxRedirs: 20,
34
- acceptEncoding: '',
35
- curlyStreamUpload: nodeReadable,
36
- // this will just make libcurl use their own progress function (which is pretty neat)
37
- // curlyProgressCallback() { return CurlProgressFunc.Continue },
38
- // verbose: true,
39
- httpHeader: curlyHeaders,
40
- customRequest: fetchRequest.method,
41
- };
42
46
  if (size != null) {
43
- curlyOptions.inFileSize = size;
47
+ curlHandle.setOpt('INFILESIZE', size);
44
48
  }
45
- const { curly, CurlCode, CurlPause } = globalThis['libcurl'];
46
- if (fetchRequest['_signal']) {
47
- fetchRequest['_signal'].onabort = () => {
48
- if (easyNativeBinding != null) {
49
- easyNativeBinding.pause(CurlPause.Recv);
49
+ curlHandle.setOpt('HTTPHEADER', curlHeaders);
50
+ curlHandle.enable(CurlFeature.NoHeaderParsing);
51
+ return new Promise(function promiseResolver(resolve, reject) {
52
+ curlHandle.once('end', function endListener() {
53
+ curlHandle.close();
54
+ });
55
+ curlHandle.once('error', function errorListener(error) {
56
+ if (error.isCurlError && error.code === CurlCode.CURLE_ABORTED_BY_CALLBACK) {
57
+ // this is expected
50
58
  }
51
- };
52
- }
53
- const curlyResult = await curly(fetchRequest.url, curlyOptions);
54
- const responseHeaders = new PonyfillHeaders();
55
- curlyResult.headers.forEach(headerInfo => {
56
- for (const key in headerInfo) {
57
- if (key === 'location' || (key === 'Location' && fetchRequest.redirect === 'error')) {
58
- throw new Error('redirects are not allowed');
59
+ else {
60
+ // this is unexpected
61
+ reject(error);
59
62
  }
60
- if (key !== 'result') {
61
- responseHeaders.append(key, headerInfo[key]);
62
- }
63
- }
64
- });
65
- curlyResult.data.on('error', (err) => {
66
- if (err.isCurlError && err.code === CurlCode.CURLE_ABORTED_BY_CALLBACK) {
67
- // this is expected
68
- }
69
- else {
70
- throw err;
71
- }
72
- });
73
- return new PonyfillResponse(curlyResult.data, {
74
- status: curlyResult.statusCode,
75
- headers: responseHeaders,
76
- url: fetchRequest.url,
63
+ curlHandle.close();
64
+ });
65
+ curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
66
+ const headersFlat = headersBuf
67
+ .toString('utf8')
68
+ .split(/\r?\n|\r/g)
69
+ .filter(headerFilter => {
70
+ if (headerFilter && !headerFilter.startsWith('HTTP/')) {
71
+ if (fetchRequest.redirect === 'error' &&
72
+ (headerFilter.includes('location') || headerFilter.includes('Location'))) {
73
+ reject(new Error('redirect is not allowed'));
74
+ }
75
+ return true;
76
+ }
77
+ return false;
78
+ });
79
+ const headersInit = headersFlat.map(headerFlat => headerFlat.split(/:\s(.+)/).slice(0, 2));
80
+ resolve(new PonyfillResponse(stream, {
81
+ status,
82
+ headers: headersInit,
83
+ url: fetchRequest.url,
84
+ }));
85
+ });
86
+ curlHandle.perform();
77
87
  });
78
88
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/node-fetch",
3
- "version": "0.4.8",
3
+ "version": "0.4.9-rc-20230718150451-79c2199",
4
4
  "description": "Fetch API implementation for Node",
5
5
  "sideEffects": false,
6
6
  "dependencies": {