Легкий модуль, который приносит API Fetch API в Node.js.

Вы можете искать документы V2
Вместо реализации XMLHttpRequest в node.js для запуска полифилла для специального браузера, почему бы не перейти от нативного http в API fetch API? Следовательно, node-fetch , минимальный код для API, совместимого с window.fetch на Node.js.
См. Изоморфный нефтч Джейсона Миллера или перекрестную извлечение Леонардо Квиксада для изоморфного использования (экспорт node-fetch для сервера, whatwg-fetch для клиентской стороны).
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' ; node-fetch из V3-это модуль только ESM-вы не можете импортировать его с помощью require() .
Если вы не можете переключиться на ESM, используйте V2, который остается совместимым с CommonJS. Критические исправления ошибок будут продолжать публиковать для 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'
// ... Используете старую версию узла? Проверьте следующие файлы:
ПРИМЕЧАНИЕ. Приведенная ниже документация является актуальной с выпусками 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 ) ; URLSearchParams доступен на глобальном объекте в node.js по состоянию на V10.0.0. См. Официальную документацию для получения дополнительных методов использования.
ПРИМЕЧАНИЕ. Заголовок Content-Type только устанавливается автоматически на x-www-form-urlencoded когда экземпляр URLSearchParams определяется как таковые:
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() , см. Следующий раздел.
Обертывание функции Fetch в блок try/catch затронет все исключения, такие как ошибки, исходящие из библиотек Core Node, такие как сетевые ошибки, и эксплуатационные ошибки, которые являются экземплярами 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 не хранятся по умолчанию. Тем не менее, файлы cookie могут быть извлечены и переданы путем манипулирования запросами и заголовками ответов. См. Заголовок Extract Set-Cookie для деталей.
«Way node.js Way» - это использование потоков, когда это возможно. Вы можете 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, поэтому вам нужно сделать дополнительную работу, чтобы убедиться, что вы обрабатываете ошибки непосредственно из потока и ждать ответа на его полностью закрыть.
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' ) ) ; В отличие от браузеров, вы можете получить доступ к сырым заголовкам Set-Cookie вручную, используя Headers.raw() . Это API только node-fetch .
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 )Узел-вышивка поставляется со спецификационными реализациями FormData для публикации Multipart/Form Data Power Loads
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 )Если вам по какой-то причине вам нужно опубликовать поток, поступающий из какого-либо произвольного места, то вы можете добавить каплей или элемент, подобный файлу.
Минимальное требование состоит в том, что он имеет:
Symbol.toStringTag getter или свойство, которое либо Blob , либо Filestream() , либо метод arrayBuffer() , который возвращает ArrayBuffer. stream() должен возвращать любой асинхровой итерабильный объект, если он дает Uint8Array (или Buffer), чтобы Node.Roadable Streams и WhatWG потоки работают просто отлично.
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 .
Пример времени запроса через 150 мс может быть достигнут в качестве следующего:
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 -адрес для извлеченияoptions для запроса HTTP (S)Promise<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 , чтобы по умолчанию было верно. Если вы хотите включить keepalive в более ранней версии node.js, вы можете переопределить агент в соответствии с следующим образцом кода.
Кроме того, опция agent принимает функцию, которая возвращает http (ы) .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 имеет меньший внутренний размер буфера (16 КБ, он же highWaterMark ) из браузеров на стороне клиента (> 1 МБ, не согласованно между браузерами). Из -за этого, когда вы пишете изоморфное приложение и используете 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 ) ; Перенесен на опцию insecureHTTPParser на http (s) .request. См. http.request для получения дополнительной информации.
Опция 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 (S), содержащий информацию о URL, методе, заголовках и корпусе. Этот класс реализует интерфейс корпуса.
Из -за характера Node.js в данный момент не реализуются следующие свойства:
typedestinationmodecredentialscacheintegritykeepaliveСледующие свойства удлинения узла выдвигаются:
followcompresscounteragenthighWaterMarkСм. Параметры точного значения этих расширений.
(Специально)
input строку, представляющую URL или другой Request (который будет клонирован)options для запроса HTTP (S) Создает новый объект Request . Конструктор идентичен тем, что в браузере.
В большинстве случаев непосредственно fetch(url, options) проще, чем создание объекта Request .
Ответ HTTP (S). Этот класс реализует интерфейс корпуса.
Следующие свойства в данный момент не реализуются в узел.
trailer(Специально)
body String или Readable потокаoptions - словарь вариантов ResponseInit Создает новый объект Response . Конструктор идентичен тем, что в браузере.
Поскольку node.js не внедряет работников обслуживания (для которых был разработан этот класс), редко приходится напрямую построить Response .
(Специально)
Удобное свойство, представляющее, если запрос закончился нормально. Оцените до True, если статус ответа был больше или равным 200, но меньше 300.
(Специально)
Удобное свойство, представляющее, если запрос был перенаправлен не реже одного раза один раз. Оцените True, если внутренний счетчик перенаправления больше 0.
(отклонение от спецификации)
Удобное свойство, представляющее тип ответа. Node-Fetch поддерживает только 'default' и 'error' и не использует фильтрованные ответы.
Этот класс позволяет манипулировать и итерации над набором заголовков HTTP. Все методы, указанные в стандарте Fetch, реализованы.
(Специально)
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 . Обратите внимание, что, хотя стандарт Fetch требует, чтобы свойство всегда было ReadableStream WhatWG, в сгибке узла это Readable поток Node.js.
(Специально)
BooleanЛогическое свойство для того, если это тело было потреблено. Согласно спецификациям, потребляемое тело не может быть использовано снова.
fetch поставляется с методами для анализа multipart/form-data полезных нагрузок, а также с x-www-form-urlencoded Bodies с использованием .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 ( )
} )(расширение узел)
Эксплуатационная ошибка в процессе извлечения. См. Ошибка handling.md для получения дополнительной информации.
(расширение узел)
Ошибка, выдвинутая при прерывании запроса в ответ на событие abort AbortSignal . У него есть name AbortError . См. Ошибка handling.md для получения дополнительной информации.
Поскольку типы 3.x объединены с помощью node-fetch , поэтому вам не нужно устанавливать какие-либо дополнительные пакеты.
Для старых версий, пожалуйста, используйте определения типов от определенности:
npm install --save-dev @types/[email protected]Благодаря GitHub/Fetch за предоставление надежной ссылки на реализацию.
![]() | ![]() | ![]() | ![]() | ![]() |
|---|---|---|---|---|
| Дэвид Франк | Джимми Вартинг | Антони Кепински | Ричи Бендалл | Грегор Мартинус |
Грань