JavaScript >> Javascript 文檔 >  >> Node.js

Node.js 請求模塊

如今,我們的 Web 應用程序傾向於與其他服務進行大量集成,無論是與 Twitter 等 REST 服務交互,還是從 Flickr 下載圖像。使用 Node/JavaScript 是處理此類應用程序的最流行的語言之一。無論哪種方式,你都會發出大量的 HTTP 請求,這意味著你需要一個可靠的模塊來讓編寫代碼變得更容易接受。

request 模塊是迄今為止最流行的(非標準)用於發出 HTTP 請求的 Node 包。實際上,它實際上只是 Node 內置 http 模塊的一個包裝器,因此您可以使用 http 自己實現所有相同的功能 , 但 request 只是讓它變得更容易。

發出 HTTP 請求

雖然 request 中有很多選項可供您使用 (我們將在本文中介紹其中的許多內容),使用起來也非常簡單。這個庫的“hello world”示例就像傳遞 URL 和回調一樣簡單:

const request = require('request');

request('http://stackabuse.com', function(err, res, body) {
    console.log(body);
});

上面的代碼向 stackabuse.com 提交一個 HTTP GET 請求,然後將返回的 HTML 打印到屏幕上。這種類型的請求適用於任何 HTTP 端點,無論它返回 HTML、JSON、圖像還是其他任何東西。

request 的第一個參數 可以是 URL 字符串,也可以是選項對象。以下是您在應用程序中會遇到的一些更常見的選項:

  • url :HTTP 請求的目標 URL
  • method :要使用的 HTTP 方法(GET、POST、DELETE 等)
  • headers :要在請求中設置的 HTTP 標頭(鍵值)對象
  • form :包含鍵值表單數據的對象
const request = require('request');

const options = {
    url: 'https://www.reddit.com/r/funny.json',
    method: 'GET',
    headers: {
        'Accept': 'application/json',
        'Accept-Charset': 'utf-8',
        'User-Agent': 'my-reddit-client'
    }
};

request(options, function(err, res, body) {
    let json = JSON.parse(body);
    console.log(json);
});

使用 options 對象,此請求使用 GET 方法直接從 Reddit 檢索 JSON 數據,該數據在 body 中以字符串形式返回 場地。從這裡,您可以使用 JSON.parse 並將數據用作普通的 JavaScript 對象。

這種相同的請求格式可用於任何類型的 HTTP 方法,無論是 DELETE、PUT、POST 還是 OPTIONS。雖然,並非所有方法都使用完全相同。有些,如 POST 方法,可以在請求中包含數據。有幾種方式可以發送這些數據,其中一些是:

  • body :一個 Buffer , String , 或 Stream 對象(如果 json 可以是對象 選項設置為 true )
  • form :鍵值對數據的對象(我們稍後會介紹)
  • multipart :可以包含自己的標題和正文屬性的對像數組

每個都滿足不同的需求(還有更多發送數據的方法,可以在請求的自述文件的這一部分中找到)。 request 模塊確實包含一些方便的方法,使它們更容易使用,但是,請務必閱讀完整的文檔以避免使您的代碼變得更加困難。

說到輔助方法,調用不同 HTTP 方法的更簡潔的方法是使用提供的相應輔助方法。以下是一些比較常用的:

  • request.get(options, callback)
  • request.post(options, callback)
  • request.head(options, callback)
  • request.delete(options, callback)

雖然這不會為您節省大量代碼行,但它至少會讓您的代碼更容易理解,因為它允許您只查看被調用的方法,而不必解析所有各種選項來查找它。

表單

無論您是與 REST API 交互,還是創建機器人以在網站上抓取和提交數據,有時您都需要為表單提交數據。與 request 一樣 ,這可以通過幾種不同的方式完成,具體取決於您的需要。

對於常規表單(URL 編碼,MIME 類型為 application/x-www-form-urlencoded ),你最好使用 .post() 使用表單對象的便捷方法:

let options = {
    url: 'http://http://mockbin.com/request',
    form: {
        email: '[email protected]',
        password: 'myPassword'
    }
};

request.post(options, callback);

這將像 HTML 表單一樣上傳數據,唯一的限制是您不能以這種方式上傳文件。為此,您需要使用 formData 而是選項,它使用下面的表單數據庫。

使用 formData 相反,我們現在可以通過 Buffer 將文件數據傳遞給服務器 s, Stream s,甚至是非文件數據(和以前一樣)具有簡單的鍵值對。

let formData = {
    // Pass single file with a key
    profile_pic: fs.createReadStream(__dirname + '/me.jpg'),

    // Pass multiple files in an array
    attachments: [
        fs.readFileSync(__dirname + '/cover-letter.docx'),  // Buffer
        fs.createReadStream(__dirname + '/resume.docx'),    // Stream
    ],

    // Pass extra meta-data with your files
    detailed_file: {
        value: fs.createReadStream(__dirname + '/my-special-file.txt'),
        options: {
            filename: 'data.json',
            contentType: 'application/json'
        }
    },

    // Simple key-value pairs
    username: 'ScottWRobinson'
};

request.post('http://http://mockbin.com/request', {formData: formData}, callback);

這將使用 multipart/form-data 的 MIME 類型發送您的文件 ,即多部分錶單上傳。

雖然這對於大多數用戶的用例來說已經綽綽有餘,但有時您需要更細粒度的控制,例如前/後 CLRF(新行)、分塊或指定您自己的多部分。有關這些額外選項的更多信息,請查看 request 的這一部分 自述文件。

在我看來,在許多編程語言中使用最少的特性之一是流。它們的用途不僅限於網絡請求,但這是一個完美的例子,說明了為什麼應該使用它們。有關如何以及為何使用它們的簡短說明,請查看 Node HTTP Servers for Static File Serving 一文的“Streams”部分。

簡而言之,對大量數據(如文件)使用流可以幫助減少應用程序的內存佔用和響應時間。為了使這個更容易使用,每個 request 方法可以pipe 他們的輸出到另一個流。

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

在此示例中,我們使用 GET 請求下載 Node.js 徽標並將其流式傳輸到本地文件:

let fileStream = fs.createWriteStream('node.png');
request('https://nodejs.org/static/images/logos/nodejs-new-white-pantone.png').pipe(fileStream);

一旦 HTTP 請求開始返回下載圖像的部分內容,它就會將該數據“管道”直接發送到文件“node.png”。

以這種方式下載文件還有其他一些好處。流非常適合在下載數據時對數據應用轉換。因此,例如,假設您正在使用 request 下載大量敏感數據 需要立即加密。為此,您可以通過管道輸出 request 來應用加密轉換 到crypto.createCipher:

let url = 'http://example.com/super-sensitive-data.json';
let pwd = new Buffer('myPassword');

let aesTransform = crypto.createCipher('aes-256-cbc', pwd);
let fileStream = fs.createWriteStream('encrypted.json');

request(url)
    .pipe(aesTransform)     // Encrypts with aes256
    .pipe(fileStream)       // Write encrypted data to a file
    .on('finish', function() {
        console.log('Done downloading, encrypting, and saving!');
    });

很容易忽略流,很多人在編寫代碼時都會這樣做,但是它們可以極大地幫助您提高性能,尤其是對於像 request 這樣的庫 .

雜項。配置

HTTP 請求不僅僅是指定 URL 和下載數據。對於較大的應用程序,尤其是那些必須支持更廣泛環境的應用程序,您的請求可能需要處理相當多的配置參數,例如代理或特殊的 SSL 信任證書。

一項重要的雜項。要指出的功能是 request.defaults() 方法,它允許你指定默認參數,這樣你就不必為你提出的每個請求都提供它們。

let req = request.defaults({
    headers: {
        'x-access-token': '123abc',
        'User-Agent': 'my-reddit-client'
    }
});

req('http://your-api.com', function(err, res, body) {
    console.log(body);
});

現在,在上面的示例中,所有使用 req 發出的請求 將始終具有標題 x-access-tokenUser-Agent 放。這非常適合設置此類標頭、代理服務器或 TLS/SSL 配置。

在本節的其餘部分,我們將介紹一些您會遇到的更常見的功能:

代理

無論您的計算機是在公司代理後面,還是您想將您的流量重定向到另一個國家,在某些時候您可能需要指定一個代理地址。實現這一點的最簡單方法是使用 proxy 選項,它需要一個代理流量的地址:

let options = {
    url: 'https://www.google.com',
    proxy: 'http://myproxy.com'
};

request(options, callback);

options object 是指定代理的一種方法,但 request 還使用以下環境變量來配置代理連接:

  • HTTP_PROXY / http_proxy
  • HTTPS_PROXY / https_proxy
  • NO_PROXY / no_proxy

這為您提供了更多控制權,例如設置哪些網站不應該 通過 NO_PROXY 代理 變量。

TLS/SSL

有時 API 需要有一些額外的安全性,因此需要客戶端證書。這實際上在私有企業 API 中相當普遍,因此值得了解如何執行此操作。

另一種可能的情況是您希望您的 HTTP 請求明確信任某些證書頒發機構,其中可能包括您或您的公司自簽名的證書。

與到目前為止我們看到的所有其他配置一樣,這些都是在 options 中設置的 對象:

const fs = require('fs');
const request = require('request');

let myCertFile = fs.readFileSync(__dirname + '/ssl/client.crt')
let myKeyFile = fs.readFileSync(__dirname + '/ssl/client.key')
let myCaFile = fs.readFileSync(__dirname + '/ssl/ca.cert.pem')
 
var options = {
    url: 'https://mockbin.com/request',
    cert: myCertFile,
    key: myKeyFile,
    passphrase: 'myPassword',
    ca: myCaFile
};
 
request.get(options);
基本認證

使用基本訪問身份驗證的站點仍然可以使用 auth 訪問 選項:

const request = require('request');
 
var options = {
    url: 'https://mockbin.com/request',
    auth: {
        username: 'ScottWRobinson',
        password: 'myPassword'
    }
};
 
request.get(options);

此選項將 HTTP 標頭之一設置為 "authorization": "Basic c2NvdHQ6cGFzc3dvcmQh" . “授權”標頭中的“基本”字符串聲明這是一個基本身份驗證請求,後面的字母數字字符串是我們的用戶名和密碼的 RFC2045-MIME 編碼(Base64 的一種變體)。

重定向

我發現在某些應用程序中,例如網頁抓取,在很多情況下您需要遵循重定向才能使您的請求成功。您可能已經猜到了,默認情況下有一個選項可以指定是否遵循重定向,但是 request 更進一步,將讓您提供一個函數,可用於有條件地確定是否應遵循重定向。

一些重定向選項是:

  • followRedirect :如果 true ,然後遵循所有 HTTP 3xx 重定向。或提交 function(res) {} 用於確定是否遵循重定向
  • followAllRedirects :遵循所有非 GET HTTP 3xx 重定向
  • maxRedirects :跟踪鏈接重定向的最大次數(默認為 10)

結論

毫無疑問request 是一個功能強大的模塊,可能是您經常使用的模塊。鑑於它提供的所有功能,它可以作為一個很好的起點,從網絡爬蟲到 API 的客戶端庫。

request 可以使用更多的選項和配置 比我們在這裡展示的更多,所以請務必查看文檔以獲取更多詳細信息。請記住,並非模塊中的所有內容都記錄在案,因此您可能需要進行更多搜索/實驗才能找到答案。

你用過request 在你的任何項目中?如果有,怎麼做?


Tutorial JavaScript 教程
  1. 糾正我對CORS的理解

  2. 讓我們在 Vue.js 中為我們的電子商務應用添加購物車功能

  3. Redux vs. React Context API vs. AppRun

  4. 如何在編程中堅持童子軍規則

  5. Javascript:程序結構

  6. Javascript – deepEqual 比較

  7. React Inbox 和 React Toast 組件用於不糟糕的通知

  1. 🚀 使用 Tailwind CSS 和 TypeScript [開源] 免費 React 登陸頁面模板 ⚡️

  2. 如何使用javascript填寫表單字段並提交?

  3. 我想實際使用的 TypeScript 枚舉

  4. 數據庫中的連接池

  5. 將任何 Meteor 應用程序轉換為 PWA

  6. 獲取 keycode JavaScript 屬性 |查找特定密鑰的密鑰代碼

  7. 將 2D JavaScript 數組轉換為 1D 數組

  1. React 導航欄教程(幻燈片)

  2. 在 VSCode 上的 Docker 容器中調試 NodeJS

  3. 您如何從一個已在另一個函數內部傳遞的函數運行函數?

  4. 網絡安全清單✔