В наши дни наши веб-приложения, как правило, часто интегрируются с другими сервисами, будь то взаимодействие с сервисом 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
: объект, содержащий данные формы "ключ-значение"
|
|
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, не связанным с GETmaxRedirects
: максимальное количество последовательных перенаправлений (по умолчанию 10).
Заключение
Без сомнения, request
- мощный модуль, который, вероятно, вы будете
часто использовать. Учитывая все предоставляемые функции, он может
служить отличной отправной точкой для чего угодно, от поискового робота
до клиентской библиотеки для вашего API.
Есть еще несколько дополнительных опций и конфигураций, которые можно
использовать с request
чем то, что мы показали здесь, поэтому
обязательно ознакомьтесь с
документацией для получения
более подробной информации. Имейте в виду, что не все в модуле
задокументировано, поэтому вам может потребоваться еще несколько поисков
/ экспериментов, чтобы найти свой ответ.
Вы использовали request
в каком-либо из своих проектов? Если да, то
как?