Modul ringan yang membawa API Fetch ke Node.js.

Anda mungkin mencari dokumen V2
Alih-alih mengimplementasikan XMLHttpRequest di Node.js untuk menjalankan fetch Polyfill khusus browser, mengapa tidak beralih dari http asli untuk fetch API secara langsung? Oleh karena itu, node-fetch , kode minimal untuk window.fetch API yang kompatibel pada runtime Node.js.
Lihat isomorphic-unsfetch Jason Miller atau Leonardo Quixada Cross-Fetch untuk penggunaan isomorfik (Ekspor node-fetch untuk Sisi Server, whatwg-fetch untuk sisi klien).
window.fetch API.res.text() dan res.json() ) ke UTF-8 secara otomatis.window.fetch , jangan ragu untuk membuka masalah. Rilis stabil saat ini ( 3.x ) membutuhkan setidaknya node.js 12.20.0.
npm install node-fetch import fetch from 'node-fetch' ; node-fetch dari V3 adalah modul khusus ESM-Anda tidak dapat mengimpornya dengan require() .
Jika Anda tidak dapat beralih ke ESM, silakan gunakan V2 yang tetap kompatibel dengan CommonJS. Perbaikan bug kritis akan terus diterbitkan untuk V2.
npm install node-fetch@2 Atau, Anda dapat menggunakan fungsi async import() dari CommonJS untuk memuat node-fetch secara asinkron:
// mod.cjs
const fetch = ( ... args ) => import ( 'node-fetch' ) . then ( ( { default : fetch } ) => fetch ( ... args ) ) ; Untuk menggunakan fetch() tanpa mengimpornya, Anda dapat menambal objek global dalam simpul:
// 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'
// ... Menggunakan versi lama Node-Fetch? Lihat file -file berikut:
Catatan: Dokumentasi di bawah ini mutakhir dengan rilis 3.x , jika Anda menggunakan versi yang lebih lama, silakan periksa cara meningkatkan.
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 tersedia di objek global di Node.js pada v10.0.0. Lihat dokumentasi resmi untuk metode penggunaan lebih lanjut.
Catatan: Header Content-Type hanya diatur secara otomatis ke x-www-form-urlencoded ketika instance URLSearchParams diberikan seperti itu:
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 ) ; Catatan: Respons 3xx-5xx bukan pengecualian, dan harus ditangani di then() , lihat bagian selanjutnya.
Membungkus fungsi pengambilan menjadi blok try/catch akan menangkap semua pengecualian, seperti kesalahan yang berasal dari pustaka inti node, seperti kesalahan jaringan, dan kesalahan operasional yang merupakan contoh fetcherror. Lihat dokumen penanganan kesalahan untuk lebih jelasnya.
import fetch from 'node-fetch' ;
try {
await fetch ( 'https://domain.invalid/' ) ;
} catch ( error ) {
console . log ( error ) ;
}Adalah umum untuk membuat fungsi helper untuk memeriksa bahwa respons tidak mengandung respons klien (4xx) atau server (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 tidak disimpan secara default. Namun, cookie dapat diekstraksi dan disahkan dengan memanipulasi permintaan dan header respons. Lihat Extract Set-Cookie Header untuk detailnya.
"Node.js Way" adalah menggunakan streaming bila memungkinkan. Anda dapat menyalurkan res.body ke aliran lain. Contoh ini menggunakan stream.pipeline untuk melampirkan penangan stream error dan menunggu unduhan selesai.
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' ) ) ; Di Node.js 14 Anda juga dapat menggunakan iterator async untuk membaca body ; Namun, berhati -hatilah untuk menangkap kesalahan - semakin lama respons berjalan, semakin besar kemungkinan untuk menghadapi kesalahan.
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 ) ;
} Di Node.js 12 Anda juga dapat menggunakan iterator async untuk membaca body ; Namun, itync iterator dengan aliran tidak matang sampai node.js 14, jadi Anda perlu melakukan beberapa pekerjaan tambahan untuk memastikan Anda menangani kesalahan langsung dari aliran dan menunggu respons untuk menutup sepenuhnya.
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' ) ) ; Tidak seperti browser, Anda dapat mengakses header Set-Cookie mentah secara manual menggunakan Headers.raw() . Ini adalah API node-fetch hanya.
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 hadir dengan implementasi FormData yang sesuai dengan spec untuk memposting muatan multipart/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 )Jika Anda karena alasan tertentu perlu memposting aliran yang datang dari tempat yang sewenang-wenang, maka Anda dapat menambahkan gumpalan atau item yang terlihat seperti file.
Persyaratan minimum adalah memiliki:
Symbol.toStringTag Blob Filestream() atau metode arrayBuffer() yang mengembalikan arraybuffer. stream() harus mengembalikan objek yang dapat diubah selama ini selama itu menghasilkan UInt8Array (atau buffer) sehingga node. Stream yang dapat dibaca dan aliran apa yang berfungsi dengan baik.
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' ) Anda dapat membatalkan permintaan dengan AbortController . Implementasi yang disarankan adalah abort-controller .
Contoh waktu keluar permintaan setelah 150 ms dapat dicapai sebagai berikut:
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 ) ;
}Lihat kasus uji untuk lebih banyak contoh.
url Sebuah string yang mewakili URL untuk pengambilanoptions untuk Permintaan HTTPPromise<Response>Lakukan pengambilan http (s).
url harus menjadi URL absolut, seperti https://example.com/ . URL jalur-relatif ( /file/under/root ) atau URL relatif protokol ( //can-be-http-or-https.com/ ) akan menghasilkan Promise yang ditolak.
Nilai default ditampilkan setelah setiap tombol opsi.
{
// 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`.
} Jika tidak ada nilai yang ditetapkan, header permintaan berikut akan dikirim secara otomatis:
| Header | Nilai |
|---|---|
Accept-Encoding | gzip, deflate, br (when options.compress === true ) |
Accept | */* |
Content-Length | (secara otomatis dihitung, jika memungkinkan) |
Host | (Informasi host dan port dari target URI) |
Transfer-Encoding | chunked (saat req.body adalah aliran) |
User-Agent | node-fetch |
CATATAN: Ketika body adalah Stream , Content-Length tidak diatur secara otomatis.
Opsi agent memungkinkan Anda untuk menentukan opsi terkait jaringan yang berada di luar ruang lingkup fetch, termasuk dan tidak terbatas pada yang berikut:
Lihat http.Agent untuk informasi lebih lanjut.
Jika tidak ada agen yang ditentukan, agen default yang disediakan oleh Node.js digunakan. Perhatikan bahwa ini berubah di node.js 19 untuk mendapatkan keepalive true secara default. Jika Anda ingin mengaktifkan keepalive dalam versi sebelumnya dari Node.js, Anda dapat mengganti agen sesuai dengan sampel kode berikut.
Selain itu, opsi agent menerima fungsi yang mengembalikan http .Agent
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 ;
}
}
} ; Stream di Node.js memiliki ukuran buffer internal yang lebih kecil (16kb, alias highWaterMark ) dari browser sisi klien (> 1MB, tidak konsisten di seluruh browser). Karena itu, ketika Anda menulis aplikasi isomorfik dan menggunakan res.clone() , itu akan menggantung dengan respons besar di node.
Cara yang disarankan untuk memperbaiki masalah ini adalah dengan menyelesaikan respons kloning secara paralel:
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 ] ) ; Jika karena alasan tertentu Anda tidak menyukai solusi di atas, karena 3.x Anda dapat memodifikasi opsi 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 ) ; Melewati opsi insecureHTTPParser di http. Lihat http.request untuk informasi lebih lanjut.
Opsi redirect: 'manual' untuk Node-Fetch berbeda dari browser & spesifikasi, yang menghasilkan respons filter yang disaring secara buram. Node-Fetch memberi Anda respons dasar yang disaring secara khas sebagai gantinya.
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 ) ;
}Permintaan HTTP (S) yang berisi informasi tentang url, metode, header, dan tubuh. Kelas ini mengimplementasikan antarmuka tubuh.
Karena sifat node.js, sifat -sifat berikut tidak diimplementasikan pada saat ini:
typedestinationmodecredentialscacheintegritykeepaliveProperti Ekstensi Node-Fetch berikut disediakan:
followcompresscounteragenthighWaterMarkLihat opsi untuk makna yang tepat dari ekstensi ini.
(patuh spec)
input string yang mewakili URL, atau Request lain (yang akan dikloning)options untuk Permintaan HTTP Membangun objek Request baru. Konstruktor identik dengan yang ada di browser.
Dalam kebanyakan kasus, fetch(url, options) lebih sederhana daripada membuat objek Request .
Respons http (s). Kelas ini mengimplementasikan antarmuka tubuh.
Properti berikut tidak diimplementasikan di Node-Fetch pada saat ini:
trailer(patuh spec)
body String atau aliran Readableoptions Kamus Opsi ResponseInit Membangun objek Response baru. Konstruktor identik dengan yang ada di browser.
Karena Node.js tidak mengimplementasikan pekerja layanan (yang dirancang kelas ini), orang jarang harus membangun Response secara langsung.
(patuh spec)
Properti kenyamanan mewakili jika permintaan berakhir secara normal. Akan mengevaluasi ke true jika status respons lebih besar dari atau sama dengan 200 tetapi lebih kecil dari 300.
(patuh spec)
Properti kenyamanan mewakili jika permintaan telah dialihkan setidaknya sekali. Akan mengevaluasi ke true jika konter pengalihan internal lebih besar dari 0.
(penyimpangan dari spec)
Properti kenyamanan mewakili jenis respons. Node-Fetch hanya mendukung 'default' dan 'error' dan tidak menggunakan respons yang difilter.
Kelas ini memungkinkan memanipulasi dan mengulangi satu set header HTTP. Semua metode yang ditentukan dalam standar fetch diimplementasikan.
(patuh spec)
init argumen opsional untuk mengisi objek Headers Bangun objek Headers baru. init dapat berupa null , objek Headers , objek peta nilai kunci atau objek yang dapat diulang.
// 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 adalah antarmuka abstrak dengan metode yang berlaku untuk kelas Request dan Response .
(penyimpangan dari spec)
Readable Data dienkapsulasi dalam objek Body . Perhatikan bahwa sementara standar pengambilan mengharuskan properti untuk selalu menjadi whatwg ReadableStream , di node-fetch itu adalah aliran Readable node.js.
(patuh spec)
BooleanProperti boolean untuk jika badan ini telah dikonsumsi. Sesuai spesifikasi, tubuh yang dikonsumsi tidak dapat digunakan lagi.
fetch dilengkapi dengan metode untuk mem-parse muatan multipart/form-data serta badan x-www-form-urlencoded menggunakan .formData() Ini berasal dari gagasan bahwa pekerja layanan dapat mencegat pesan tersebut sebelum dikirim ke server untuk mengubahnya. Ini berguna bagi siapa pun yang membangun server sehingga Anda dapat menggunakannya untuk menguraikan & mengkonsumsi muatan.
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 ( )
} )(Ekstensi Node-Fetch)
Kesalahan operasional dalam proses pengambilan. Lihat kesalahan-handling.md untuk info lebih lanjut.
(Ekstensi Node-Fetch)
Kesalahan yang dilemparkan ketika permintaan dibatalkan sebagai tanggapan terhadap peristiwa abort AbortSignal . Ini memiliki properti name AbortError . Lihat kesalahan-handling.md untuk info lebih lanjut.
Karena tipe 3.x dibundel dengan node-fetch , jadi Anda tidak perlu menginstal paket tambahan apa pun.
Untuk versi yang lebih lama, silakan gunakan definisi tipe dari pasti:
npm install --save-dev @types/[email protected]Terima kasih kepada GitHub/Fetch untuk memberikan referensi implementasi yang solid.
![]() | ![]() | ![]() | ![]() | ![]() |
|---|---|---|---|---|
| David Frank | Jimmy Wärting | Antoni Kepinski | Richie Bendall | Gregor Martynus |
Mit