Модуль запроса Node.js

В наши дни наши веб-приложения, как правило, часто интегрируются с другими сервисами, будь то взаимодействие с сервисом REST, например Twitter, или загрузка изображений с Flickr. Использование Node / JavaScript - один из самых популярных языков для работы с подобными приложениями. В любом случае вы будете делать много HTTP-запросов, а это значит, что вам понадобится надежный модуль, чтобы сделать написание кода более терпимым. Модуль запроса [https://www.npmjs.com/package/request] на сегодняшний день является самым популярным

В наши дни наши веб-приложения, как правило, часто интегрируются с другими сервисами, будь то взаимодействие с сервисом REST, например Twitter, или загрузка изображений с Flickr. Использование Node / JavaScript - один из самых популярных языков для работы с подобными приложениями. В любом случае вы будете делать много HTTP-запросов, а это значит, что вам понадобится надежный модуль, чтобы сделать написание кода более терпимым.

Модуль запроса - безусловно, самый популярный (нестандартный) пакет Node для выполнения HTTP-запросов. На самом деле, это просто оболочка для встроенного в Node http- модуля, так что вы можете добиться тех же функций самостоятельно с помощью http , но request делает это намного проще.

Выполнение HTTP-запросов

request вам доступно довольно много опций (многие из которых мы рассмотрим в этой статье), он также может быть довольно простым в использовании. Пример "hello world" для этой библиотеки так же прост, как передача URL-адреса и обратного вызова:

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

Приведенный выше код отправляет HTTP-запрос GET на stackabuse.com, а затем выводит возвращенный HTML-код на экран. Этот тип запроса работает для любой конечной точки HTTP, независимо от того, возвращает ли он HTML, JSON, изображение или что-то еще.

Первым аргументом request может быть строка URL-адреса или объект параметров. Вот некоторые из наиболее распространенных вариантов, с которыми вы столкнетесь в своих приложениях:

  • url : целевой URL-адрес HTTP-запроса.
  • method : используемый HTTP-метод (GET, POST, DELETE и т. д.)
  • headers : объект заголовков HTTP (ключ-значение), который будет установлен в запросе.
  • form : объект, содержащий данные формы "ключ-значение"
1
<!-- -->
 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 для извлечения данных JSON непосредственно из Reddit, которые возвращаются в виде строки в поле body Отсюда вы можете использовать JSON.parse и использовать данные как обычный объект JavaScript.

Этот же формат запроса можно использовать для любого типа HTTP-метода , будь то DELETE, PUT, POST или OPTIONS. Хотя не все методы используются одинаково. Некоторые, например метод POST, могут включать данные в запрос. Есть несколько способов отправки этих данных, в том числе:

  • body : Buffer , String или Stream (может быть объектом, если для json установлено значение true )
  • form : объект данных пары ключ-значение (мы рассмотрим это позже)
  • multipart : массив объектов, который может содержать собственные заголовки и атрибуты тела.

Каждый из них удовлетворяет разные потребности (и существует еще больше способов отправки данных, которые можно найти в этом разделе README запроса ). Модуль 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 или даже нефайловые данные (как раньше) с простыми парами ключ-значение.

 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); 

Это отправит ваши файлы с MIME-типом multipart/form-data , который представляет собой загрузку составной формы.

Хотя этого будет более чем достаточно для большинства пользовательских сценариев использования, бывают случаи, когда вам требуется еще более детальный контроль, например, до / после CLRF (новые строки), разбиение на фрагменты или указание ваших собственных составных частей. Для получения дополнительной информации об этих дополнительных параметрах ознакомьтесь с этим разделом request README .

Потоки

На мой взгляд, одна из самых малоиспользуемых функций во многих языках программирования - это потоки. Их полезность не ограничивается только сетевыми запросами, но это прекрасный пример того, почему вы должны их использовать. Краткое описание того, как и почему вы должны их использовать, можно найти в разделе «Потоки» статьи HTTP-серверы узла для обслуживания статических файлов .

Короче говоря, использование потоков для больших объемов данных (например, файлов) может помочь уменьшить объем памяти и время отклика вашего приложения. Чтобы сделать это проще в использовании, каждый из request методов может pipe их выход в другой поток.

В этом примере мы загружаем логотип Node.js с помощью запроса GET и передаем его в локальный файл:

 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-token и User-Agent . Это идеально подходит для настройки таких заголовков, прокси-серверов или конфигураций TLS / SSL.

В оставшейся части этого раздела мы рассмотрим еще несколько общих функций, с которыми вы столкнетесь:

Прокси

Независимо от того, находится ли ваш компьютер за корпоративным прокси-сервером или вы хотите перенаправить свой трафик в другую страну, в какой-то момент вам может потребоваться указать адрес прокси. Самый простой способ добиться этого - использовать proxy , которая принимает адрес, через который проксируется трафик:

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

Объект options - это один из способов указать прокси, но 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 : следовать всем перенаправлениям HTTP 3xx, не связанным с GET
  • maxRedirects : максимальное количество последовательных перенаправлений (по умолчанию 10).

Заключение

Без сомнения, request - мощный модуль, который, вероятно, вы будете часто использовать. Учитывая все предоставляемые функции, он может служить отличной отправной точкой для чего угодно, от поискового робота до клиентской библиотеки для вашего API.

Есть еще несколько дополнительных опций и конфигураций, которые можно использовать с request чем то, что мы показали здесь, поэтому обязательно ознакомьтесь с документацией для получения более подробной информации. Имейте в виду, что не все в модуле задокументировано, поэтому вам может потребоваться еще несколько поисков / экспериментов, чтобы найти свой ответ.

Вы использовали request в каком-либо из своих проектов? Если да, то как?

comments powered by Disqus