一个轻巧的模块,将fetch api带到node.js。

您可能正在寻找V2文档
与其在node.js中实现XMLHttpRequest以运行特定于浏览器的获取polyfill,为什么不直接从本机http转到fetch API呢?因此,node for window.fetch的node-fetch ,最小代码。
请参阅Jason Miller的同构不取,或Leonardo Quixada的同构用法(用于服务器端的Exports node-fetch , whatwg-fetch for client端)。
window.fetch api保持一致。res.text()和res.json() )自动转换为UTF-8。window.fetch缺失功能。当前稳定版本( 3.x )至少需要Node.js 12.20.0。
npm install node-fetch import fetch from 'node-fetch' ; V3的node-fetch是一个仅ESM的模块 - 您无法使用require()导入它。
如果您不能切换到ESM,请使用与CommonJ兼容的V2。关键的错误修复将继续为V2发布。
npm install node-fetch@2另外,您可以使用async import()函数从commonjs加载node-fetch异步:
// mod.cjs
const fetch = ( ... args ) => import ( 'node-fetch' ) . then ( ( { default : fetch } ) => fetch ( ... args ) ) ;要使用fetch()而不导入它,您可以在节点中修补global对象:
// fetch-polyfill.js
import fetch , {
Blob ,
blobFrom ,
blobFromSync ,
File ,
fileFrom ,
fileFromSync ,
FormData ,
Headers ,
Request ,
Response ,
} from 'node-fetch'
if ( ! globalThis . fetch ) {
globalThis . fetch = fetch
globalThis . Headers = Headers
globalThis . Request = Request
globalThis . Response = Response
}
// index.js
import './fetch-polyfill'
// ... 使用旧版本的node-fetch?查看以下文件:
注意:下面的文档是最新的3.x版本,如果您使用的是旧版本,请检查如何升级。
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://github.com/' ) ;
const body = await response . text ( ) ;
console . log ( body ) ; import fetch from 'node-fetch' ;
const response = await fetch ( 'https://api.github.com/users/github' ) ;
const data = await response . json ( ) ;
console . log ( data ) ; import fetch from 'node-fetch' ;
const response = await fetch ( 'https://httpbin.org/post' , { method : 'POST' , body : 'a=1' } ) ;
const data = await response . json ( ) ;
console . log ( data ) ; import fetch from 'node-fetch' ;
const body = { a : 1 } ;
const response = await fetch ( 'https://httpbin.org/post' , {
method : 'post' ,
body : JSON . stringify ( body ) ,
headers : { 'Content-Type' : 'application/json' }
} ) ;
const data = await response . json ( ) ;
console . log ( data ) ;从v10.0.0开始,在node.js中的全局对象上可用URLSearchParams 。有关更多用法方法,请参见官方文档。
注意:当URLSearchParams的实例提供时, Content-Type标头仅自动设置为x-www-form-urlencoded :
import fetch from 'node-fetch' ;
const params = new URLSearchParams ( ) ;
params . append ( 'a' , 1 ) ;
const response = await fetch ( 'https://httpbin.org/post' , { method : 'POST' , body : params } ) ;
const data = await response . json ( ) ;
console . log ( data ) ;注意:3xx-5xx响应不是例外,应在then()中处理,请参见下一节。
将获取函数包装到try/catch块中将捕获所有异常,例如源自节点核心库(例如网络错误)的错误,以及fetcherror实例的操作错误。有关更多详细信息,请参见错误处理文档。
import fetch from 'node-fetch' ;
try {
await fetch ( 'https://domain.invalid/' ) ;
} catch ( error ) {
console . log ( error ) ;
}创建辅助功能是通常的,以检查响应是否包含客户端(4xx)或服务器(5xx)错误响应:
import fetch from 'node-fetch' ;
class HTTPResponseError extends Error {
constructor ( response ) {
super ( `HTTP Error Response: ${ response . status } ${ response . statusText } ` ) ;
this . response = response ;
}
}
const checkStatus = response => {
if ( response . ok ) {
// response.status >= 200 && response.status < 300
return response ;
} else {
throw new HTTPResponseError ( response ) ;
}
}
const response = await fetch ( 'https://httpbin.org/status/400' ) ;
try {
checkStatus ( response ) ;
} catch ( error ) {
console . error ( error ) ;
const errorBody = await error . response . text ( ) ;
console . error ( `Error body: ${ errorBody } ` ) ;
}默认情况下不会存储cookie。但是,可以通过操纵请求和响应标题来提取饼干并通过。有关详细信息,请参见提取物set-cookie标头。
“ node.js方法”是在可能的情况下使用流。您可以将res.body带到另一个流。此示例使用Stream.Pipeline附加流误差处理程序并等待下载完成。
import { createWriteStream } from 'node:fs' ;
import { pipeline } from 'node:stream' ;
import { promisify } from 'node:util'
import fetch from 'node-fetch' ;
const streamPipeline = promisify ( pipeline ) ;
const response = await fetch ( 'https://github.githubassets.com/images/modules/logos_page/Octocat.png' ) ;
if ( ! response . ok ) throw new Error ( `unexpected response ${ response . statusText } ` ) ;
await streamPipeline ( response . body , createWriteStream ( './octocat.png' ) ) ;在Node.js 14中,您也可以使用异步迭代器读取body ;但是,请小心捕获错误 - 响应越长,遇到错误的可能性就越大。
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://httpbin.org/stream/3' ) ;
try {
for await ( const chunk of response . body ) {
console . dir ( JSON . parse ( chunk . toString ( ) ) ) ;
}
} catch ( err ) {
console . error ( err . stack ) ;
}在Node.js 12中,您还可以使用异步迭代器读取body ;但是,在Node.js 14之前,具有流的异步迭代器才成熟,因此您需要做一些额外的工作以确保直接从流中处理错误,并等待IT响应才能完全关闭。
import fetch from 'node-fetch' ;
const read = async body => {
let error ;
body . on ( 'error' , err => {
error = err ;
} ) ;
for await ( const chunk of body ) {
console . dir ( JSON . parse ( chunk . toString ( ) ) ) ;
}
return new Promise ( ( resolve , reject ) => {
body . on ( 'close' , ( ) => {
error ? reject ( error ) : resolve ( ) ;
} ) ;
} ) ;
} ;
try {
const response = await fetch ( 'https://httpbin.org/stream/3' ) ;
await read ( response . body ) ;
} catch ( err ) {
console . error ( err . stack ) ;
} import fetch from 'node-fetch' ;
const response = await fetch ( 'https://github.com/' ) ;
console . log ( response . ok ) ;
console . log ( response . status ) ;
console . log ( response . statusText ) ;
console . log ( response . headers . raw ( ) ) ;
console . log ( response . headers . get ( 'content-type' ) ) ;与浏览器不同,您可以使用Headers.raw()手动访问RAW Set-Cookie标头。这是一个仅node-fetch API。
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://example.com' ) ;
// Returns an array of values, instead of a string of comma-separated values
console . log ( response . headers . raw ( ) [ 'set-cookie' ] ) ; import fetch , {
Blob ,
blobFrom ,
blobFromSync ,
File ,
fileFrom ,
fileFromSync ,
} from 'node-fetch'
const mimetype = 'text/plain'
const blob = fileFromSync ( './input.txt' , mimetype )
const url = 'https://httpbin.org/post'
const response = await fetch ( url , { method : 'POST' , body : blob } )
const data = await response . json ( )
console . log ( data )Node-fetch带有符合规格的FormData实现,用于发布多个型号/form-data有效载荷
import fetch , { FormData , File , fileFrom } from 'node-fetch'
const httpbin = 'https://httpbin.org/post'
const formData = new FormData ( )
const binary = new Uint8Array ( [ 97 , 98 , 99 ] )
const abc = new File ( [ binary ] , 'abc.txt' , { type : 'text/plain' } )
formData . set ( 'greeting' , 'Hello, world!' )
formData . set ( 'file-upload' , abc , 'new name.txt' )
const response = await fetch ( httpbin , { method : 'POST' , body : formData } )
const data = await response . json ( )
console . log ( data )如果您出于某种原因需要发布来自任何任意位置的流,那么您可以附加斑点或类似a的文件。
最低要求是它具有:
Symbol.toStringTag或Blob或File属性stream()方法或arrayBuffer()方法。只要它产生uint8array(或buffer),因此stream()必须返回任何异步峰值对象。
formData . append ( 'upload' , {
[ Symbol . toStringTag ] : 'Blob' ,
size : 3 ,
* stream ( ) {
yield new Uint8Array ( [ 97 , 98 , 99 ] )
} ,
arrayBuffer ( ) {
return new Uint8Array ( [ 97 , 98 , 99 ] ) . buffer
}
} , 'abc.txt' )您可以使用AbortController取消请求。建议的实现是abort-controller 。
可以在150ms之后提出请求的一个示例如下:
import fetch , { AbortError } from 'node-fetch' ;
// AbortController was added in node v14.17.0 globally
const AbortController = globalThis . AbortController || await import ( 'abort-controller' )
const controller = new AbortController ( ) ;
const timeout = setTimeout ( ( ) => {
controller . abort ( ) ;
} , 150 ) ;
try {
const response = await fetch ( 'https://example.com' , { signal : controller . signal } ) ;
const data = await response . json ( ) ;
} catch ( error ) {
if ( error instanceof AbortError ) {
console . log ( 'request was aborted' ) ;
}
} finally {
clearTimeout ( timeout ) ;
}有关更多示例,请参见测试用例。
url代表url的字符串以获取optionsPromise<Response>执行HTTP(S)提取。
url应该是绝对的URL,例如https://example.com/ 。路径相关的URL( /file/under/root )或协议相关的URL( //can-be-http-or-https.com/ )将导致拒绝的Promise 。
在每个选项键之后显示默认值。
{
// These properties are part of the Fetch Standard
method : 'GET' ,
headers : { } , // Request headers. format is the identical to that accepted by the Headers constructor (see below)
body : null , // Request body. can be null, or a Node.js Readable stream
redirect : 'follow' , // Set to `manual` to extract redirect headers, `error` to reject redirect
signal : null , // Pass an instance of AbortSignal to optionally abort requests
// The following properties are node-fetch extensions
follow : 20 , // maximum redirect count. 0 to not follow redirect
compress : true , // support gzip/deflate content encoding. false to disable
size : 0 , // maximum response body size in bytes. 0 to disable
agent : null , // http(s).Agent instance or function that returns an instance (see below)
highWaterMark : 16384 , // the maximum number of bytes to store in the internal buffer before ceasing to read from the underlying resource.
insecureHTTPParser : false // Use an insecure HTTP parser that accepts invalid HTTP headers when `true`.
} 如果未设置值,则将自动发送以下请求标头:
| 标题 | 价值 |
|---|---|
Accept-Encoding | gzip, deflate, br (当options.compress === true时) |
Accept | */* |
Content-Length | (如果可能的话,会自动计算) |
Host | (来自目标URI的主机和端口信息) |
Transfer-Encoding | chunked (当req.body是流时) |
User-Agent | node-fetch |
注意:当body是Stream时,未自动设置Content-Length 。
agent选项允许您指定超出获取范围的网络相关选项,包括但不限于以下内容:
有关更多信息,请参见http.Agent 。
如果未指定代理,则使用node.js提供的默认代理。请注意,这在Node.js 19中更改为默认情况下具有keepalive true。如果您希望在较早版本的node.js中启用keepalive ,则可以根据以下代码示例覆盖代理。
此外, agent选项接受一个返回http (s)的函数.Agent给定当前URL,这在跨HTTP和HTTPS协议的重定向链中很有用。
import http from 'node:http' ;
import https from 'node:https' ;
const httpAgent = new http . Agent ( {
keepAlive : true
} ) ;
const httpsAgent = new https . Agent ( {
keepAlive : true
} ) ;
const options = {
agent : function ( _parsedURL ) {
if ( _parsedURL . protocol == 'http:' ) {
return httpAgent ;
} else {
return httpsAgent ;
}
}
} ; Node.js上的流具有较小的内部缓冲区大小(16KB,又名highWaterMark ),可从客户端浏览器(> 1MB,在浏览器中不一致)。因此,当您编写同构应用程序并使用res.clone()时,它将在节点中悬挂较大的响应。
解决此问题的推荐方法是并行解决克隆的响应:
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://example.com' ) ;
const r1 = response . clone ( ) ;
const results = await Promise . all ( [ response . json ( ) , r1 . text ( ) ] ) ;
console . log ( results [ 0 ] ) ;
console . log ( results [ 1 ] ) ;如果由于某种原因您不喜欢上面的解决方案,则因为3.x ,您可以修改highWaterMark选项:
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://example.com' , {
// About 1MB
highWaterMark : 1024 * 1024
} ) ;
const result = await res . clone ( ) . arrayBuffer ( ) ;
console . dir ( result ) ; 通过HTTP(s)上的insecureHTTPParser选项传递。有关更多信息,请参见http.request 。
Node-fetch的redirect: 'manual'选项不同于浏览器和规范,这导致了不透明的重新定义过滤响应。 Node-fetch为您提供了典型的基本过滤响应。
import fetch from 'node-fetch' ;
const response = await fetch ( 'https://httpbin.org/status/301' , { redirect : 'manual' } ) ;
if ( response . status === 301 || response . status === 302 ) {
const locationURL = new URL ( response . headers . get ( 'location' ) , response . url ) ;
const response2 = await fetch ( locationURL , { redirect : 'manual' } ) ;
console . dir ( response2 ) ;
}HTTP请求,其中包含有关URL,方法,标头和身体的信息。该课程实现身体接口。
由于node.js的性质,目前尚未实现以下属性:
typedestinationmodecredentialscacheintegritykeepalive提供了以下节点 - 提取扩展属性:
followcompresscounteragenthighWaterMark有关这些扩展的确切含义,请参见选项。
(符合规格)
input代表URL或其他Request字符串(将被克隆)options构建一个新的Request对象。构造函数与浏览器中的构造函数相同。
在大多数情况下,直接fetch(url, options)比创建Request对象更简单。
HTTP响应。该课程实现身体接口。
目前尚未在Node-fetch中实现以下属性:
trailer(符合规格)
body String或Readable流options ResponseInit选项词典构建一个新的Response对象。构造函数与浏览器中的构造函数相同。
由于Node.js没有实施服务工作者(为此类型的设计),因此很少需要直接构建Response 。
(符合规格)
便利属性表示请求是否正常结束。如果响应状态大于或等于200但小于300,则将评估为true。
(符合规格)
便利属性表示请求至少重定向一次。如果内部重定向计数器大于0,将评估为true。
(偏离规格)
便利属性代表响应类型。 Node-fetch仅支持'default'和'error' ,并且不使用过滤的响应。
该课程允许在一组HTTP标头上操纵和迭代。提取标准中指定的所有方法均已实现。
(符合规格)
init可选参数以预填充Headers对象构建一个新的Headers对象。 init可以是null , Headers对象,键值映射对象或任何可迭代的对象。
// Example adapted from https://fetch.spec.whatwg.org/#example-headers-class
import { Headers } from 'node-fetch' ;
const meta = {
'Content-Type' : 'text/xml'
} ;
const headers = new Headers ( meta ) ;
// The above is equivalent to
const meta = [ [ 'Content-Type' , 'text/xml' ] ] ;
const headers = new Headers ( meta ) ;
// You can in fact use any iterable objects, like a Map or even another Headers
const meta = new Map ( ) ;
meta . set ( 'Content-Type' , 'text/xml' ) ;
const headers = new Headers ( meta ) ;
const copyOfHeaders = new Headers ( headers ) ;Body是一种抽象接口,具有适用于Request和Response类的方法。
(偏离规格)
Readable流数据封装在Body对象中。请注意,虽然获取标准要求属性始终为Whatwg ReadableStream ,但在节点fetch中,它是一个node.js Readable流。
(符合规格)
Boolean如果该尸体被消耗掉,则是布尔属性的。根据规格,无法再次使用消耗的身体。
fetch带来了使用.formData()的x-www-form-urlencoded Body的方法来解析multipart/form-data有效负载,这是从.formdata()的主体,这来自于这样的想法,即服务工作者可以在发送到服务器之前拦截该消息以更改它们。这对于任何构建服务器的人都很有用,因此您可以使用它来解析和消费有效载荷。
import http from 'node:http'
import { Response } from 'node-fetch'
http . createServer ( async function ( req , res ) {
const formData = await new Response ( req , {
headers : req . headers // Pass along the boundary value
} ) . formData ( )
const allFields = [ ... formData ]
const file = formData . get ( 'uploaded-files' )
const arrayBuffer = await file . arrayBuffer ( )
const text = await file . text ( )
const whatwgReadableStream = file . stream ( )
// other was to consume the request could be to do:
const json = await new Response ( req ) . json ( )
const text = await new Response ( req ) . text ( )
const arrayBuffer = await new Response ( req ) . arrayBuffer ( )
const blob = await new Response ( req , {
headers : req . headers // So that `type` inherits `Content-Type`
} . blob ( )
} )(node-fetch扩展)
在获取过程中的操作错误。有关更多信息,请参见错误处理。md。
(node-fetch扩展)
当请求响应AbortSignal的abort事件而流产时,错误的错误。它具有AbortError的name属性。有关更多信息,请参见错误处理。md。
由于3.x类型与node-fetch捆绑在一起,因此您无需安装任何其他软件包。
对于较旧的版本,请使用esealy typed的类型定义:
npm install --save-dev @types/[email protected]感谢GitHub/Fetch提供了可靠的实现参考。
![]() | ![]() | ![]() | ![]() | ![]() |
|---|---|---|---|---|
| 大卫·弗兰克(David Frank) | 吉米·瓦特 | Antoni Kepinski | 里奇·本德尔(Richie Bendall) | 格雷戈尔·马丁努斯(Gregor Martynus) |
麻省理工学院