Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6ff3100

Browse files
authoredNov 24, 2021
feat: replace node-fetch with builtin (#834)
1 parent 8caad10 commit 6ff3100

File tree

4 files changed

+80
-18
lines changed

4 files changed

+80
-18
lines changed
 

‎src/helpers/functions.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ exports.generateFunctions = async (
2222
await ensureDir(join(functionsDir, func))
2323
await writeFile(join(functionsDir, func, `${func}.js`), handlerSource)
2424
await copyFile(bridgeFile, join(functionsDir, func, 'bridge.js'))
25+
await copyFile(
26+
join(__dirname, '..', '..', 'lib', 'templates', 'handlerUtils.js'),
27+
join(functionsDir, func, 'handlerUtils.js'),
28+
)
2529
}
2630

2731
await writeHandler(HANDLER_FUNCTION_NAME, false)

‎src/templates/getHandler.js

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
/* eslint-disable max-lines-per-function */
2-
const { promises, createWriteStream, existsSync } = require('fs')
1+
const { promises, existsSync } = require('fs')
32
const { Server } = require('http')
43
const { tmpdir } = require('os')
54
const path = require('path')
6-
const { promisify } = require('util')
75

8-
const streamPipeline = promisify(require('stream').pipeline)
96
const { Bridge } = require('@vercel/node/dist/bridge')
10-
const fetch = require('node-fetch')
7+
8+
const { downloadFile } = require('./handlerUtils')
119

1210
const makeHandler =
1311
() =>
@@ -55,14 +53,7 @@ const makeHandler =
5553

5654
// Append the path to our host and we can load it like a regular page
5755
const url = `${base}/${filePath}`
58-
console.log(`Downloading ${url} to ${cacheFile}`)
59-
const response = await fetch(url)
60-
if (!response.ok) {
61-
// Next catches this and returns it as a not found file
62-
throw new Error(`Failed to fetch ${url}`)
63-
}
64-
// Stream it to disk
65-
await streamPipeline(response.body, createWriteStream(cacheFile))
56+
await downloadFile(url, cacheFile)
6657
}
6758
// Return the cache file
6859
return readfileOrig(cacheFile, options)
@@ -163,12 +154,10 @@ const makeHandler =
163154
const getHandler = ({ isODB = false, publishDir = '../../../.next', appDir = '../../..' }) => `
164155
const { Server } = require("http");
165156
const { tmpdir } = require('os')
166-
const { promises, createWriteStream, existsSync } = require("fs");
167-
const { promisify } = require('util')
168-
const streamPipeline = promisify(require('stream').pipeline)
157+
const { promises, existsSync } = require("fs");
169158
// We copy the file here rather than requiring from the node module
170159
const { Bridge } = require("./bridge");
171-
const fetch = require('node-fetch')
160+
const { downloadFile } = require('./handlerUtils')
172161
173162
const { builder } = require("@netlify/functions");
174163
const { config } = require("${publishDir}/required-server-files.json")
@@ -186,4 +175,3 @@ exports.handler = ${
186175
`
187176

188177
module.exports = getHandler
189-
/* eslint-enable max-lines-per-function */

‎src/templates/handlerUtils.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { createWriteStream } from 'fs'
2+
import http from 'http'
3+
import https from 'https'
4+
import { pipeline } from 'stream'
5+
import { promisify } from 'util'
6+
7+
const streamPipeline = promisify(pipeline)
8+
9+
export const downloadFile = async (url, destination) => {
10+
console.log(`Downloading ${url} to ${destination}`)
11+
12+
const httpx = url.startsWith('https') ? https : http
13+
14+
await new Promise((resolve, reject) => {
15+
const req = httpx.get(url, { timeout: 10000 }, (response) => {
16+
if (response.statusCode < 200 || response.statusCode > 299) {
17+
reject(new Error(`Failed to download ${url}: ${response.statusCode} ${response.statusMessage || ''}`))
18+
return
19+
}
20+
const fileStream = createWriteStream(destination)
21+
streamPipeline(response, fileStream)
22+
.then(resolve)
23+
.catch((error) => {
24+
console.log(`Error downloading ${url}`, error)
25+
reject(error)
26+
})
27+
})
28+
req.on('error', (error) => {
29+
console.log(`Error downloading ${url}`, error)
30+
reject(error)
31+
})
32+
})
33+
}

‎test/index.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const process = require('process')
44
const os = require('os')
55
const cpy = require('cpy')
66
const { dir: getTmpDir } = require('tmp-promise')
7+
const { downloadFile } = require('../src/templates/handlerUtils')
78

89
const plugin = require('../src')
910

@@ -186,8 +187,10 @@ describe('onBuild()', () => {
186187

187188
expect(existsSync(`.netlify/internal-functions/___netlify-handler/___netlify-handler.js`)).toBeTruthy()
188189
expect(existsSync(`.netlify/internal-functions/___netlify-handler/bridge.js`)).toBeTruthy()
190+
expect(existsSync(`.netlify/internal-functions/___netlify-handler/handlerUtils.js`)).toBeTruthy()
189191
expect(existsSync(`.netlify/internal-functions/___netlify-odb-handler/___netlify-odb-handler.js`)).toBeTruthy()
190192
expect(existsSync(`.netlify/internal-functions/___netlify-odb-handler/bridge.js`)).toBeTruthy()
193+
expect(existsSync(`.netlify/internal-functions/___netlify-odb-handler/handlerUtils.js`)).toBeTruthy()
191194
})
192195

193196
test('writes correct redirects to netlifyConfig', async () => {
@@ -448,3 +451,37 @@ describe('utility functions', () => {
448451
}
449452
})
450453
})
454+
455+
describe('function helpers', () => {
456+
it('downloadFile can download a file', async () => {
457+
const url =
458+
'https://raw.githubusercontent.com/netlify/netlify-plugin-nextjs/c2668af24a78eb69b33222913f44c1900a3bce23/manifest.yml'
459+
const tmpFile = join(os.tmpdir(), 'next-test', 'downloadfile.txt')
460+
await ensureDir(path.dirname(tmpFile))
461+
await downloadFile(url, tmpFile)
462+
expect(existsSync(tmpFile)).toBeTruthy()
463+
expect(readFileSync(tmpFile, 'utf8')).toMatchInlineSnapshot(`
464+
"name: netlify-plugin-nextjs-experimental
465+
"
466+
`)
467+
await unlink(tmpFile)
468+
})
469+
470+
it('downloadFile throws on bad domain', async () => {
471+
const url = 'https://nonexistentdomain.example'
472+
const tmpFile = join(os.tmpdir(), 'next-test', 'downloadfile.txt')
473+
await ensureDir(path.dirname(tmpFile))
474+
await expect(downloadFile(url, tmpFile)).rejects.toThrowErrorMatchingInlineSnapshot(
475+
`"getaddrinfo ENOTFOUND nonexistentdomain.example"`,
476+
)
477+
})
478+
479+
it('downloadFile throws on 404', async () => {
480+
const url = 'https://example.com/nonexistentfile'
481+
const tmpFile = join(os.tmpdir(), 'next-test', 'downloadfile.txt')
482+
await ensureDir(path.dirname(tmpFile))
483+
await expect(downloadFile(url, tmpFile)).rejects.toThrowError(
484+
'Failed to download https://example.com/nonexistentfile: 404 Not Found',
485+
)
486+
})
487+
})

0 commit comments

Comments
 (0)
Please sign in to comment.