Я пытаюсь отправить HTTP-запрос на внешний API из моего приложения NodeJS. Я пробовал два разных подхода, которые нашел в Интернете, но оба не помогли с разными проблемами. Рабочая команда curl, которая приводит к правильному запросу, выглядит так:
curl -d ' { "auth_token":"XXXXXXXXX",
"hrows": [ {"cols": [ {"value":"Name 0"}, {"value":"Value 0"} ] } ],
"rows": [ {"cols": [ {"value":"Name 1"}, {"value":"Value 1"} ] },
{"cols": [ {"value":"Name 2"}, {"value":"Value 2"} ] },
{"cols": [ {"value":"Name 3"}, {"value":"Value 3"} ] },
{"cols": [ {"value":"Name 4"}, {"value":"Value 4"} ] } ]
}' http://example.com:3030/widgets/alarms
1) Попытка сделать запрос с помощью библиотеки запросов. Это не вызывает ошибки в приложении, но я получаю пустой запрос на сервере API (да, контент, который я хочу отправить, представляет собой строку)
var request = require('request');
var test = "{\"auth_token\":\"XXXXXXXXXX\", \"hrows\": [ {\"cols\": [{\"value\":\"Loc Nr.\"},{\"value\":\"Address\"},{\"value\":\"Status\"}] } ], \"rows\": [ {\"cols\": [ {\"value\":\"Name 1\"}, {\"value\":\"Value 1\"} ] }, {\"cols\": [ {\"value\":\"Name 2\"}, {\"value\":\"Value 2\"} ] } ]}";
var wid = "alarms";
postRequest(wid,test);
function postRequest(widget, content) {
var headers = {
'User-Agent': 'Super Agent/0.0.1',
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(content)
}
var options = {
traditional: true,
url: 'http://example.com:3030/widgets/'+widget,
method: 'POST',
headers: headers,
data: content,
contentType : "application/x-www-form-urlencoded"
}
console.info(options);
request.post(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
console.info(body)
}
})
}
Когда я делаю tcpdump на сервере API, я вижу, что полученный пакет похож на тот, который был получен при выполнении команды curl, за исключением того, что для поля http.content_length_header установлено значение 0 (а сам conrent отсутствует). Когда я проверяю отладочные данные переменной options, все выглядит нормально:
{ traditional: true,
url: 'http://example.com:3030/widgets/alarms',
method: 'POST',
headers:
{ 'User-Agent': 'Super Agent/0.0.1',
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': 243 },
data:
'{"auth_token":"XXXXXXXXX", "hrows": [ {"cols": [{"value":"Loc Nr."},{"value":"Address"},{"value":"Status"}] } ], "rows": [ {"cols": [ {"value":"Name 1"}, {"value":"Value 1"} ] },\t{"cols": [ {"value":"Name 2"}, {"value":"Value 2"} ] } ]}',
contentType: 'application/x-www-form-urlencoded' }
Как вы можете видеть, длина контента, а также данные есть, но не в полученном пакете (см. Прикрепленные снимки экрана, один из команды curl и один из запроса NodeJS, оба захвачены на сервере API)


Есть идеи, почему это происходит?
2) Второй способ, который я пробовал, был из сообщения Stackoverflow, которое я нашел о том, как опубликовать строку. Однако тот не справляется с
Error: connect ECONNREFUSED 127.0.0.1:80
хотя я не понимаю, почему он хочет привязаться к порту 80 на моем локальном хосте, однако метод №1 в любом случае будет предпочтительным, это просто для полноты (и, возможно, кто-то знает умный ответ на этот вопрос
var querystring = require('querystring');
var http = require('http');
var fs = require('fs');
var test = "{\"auth_token\":\"XXXXXXXX\", \"hrows\": [ {\"cols\": [{\"value\":\"Loc Nr.\"},{\"value\":\"Address\"},{\"value\":\"Status\"}] } ], \"rows\": [ {\"cols\": [ {\"value\":\"Name 1\"}, {\"value\":\"Value 1\"} ] }, {\"cols\": [ {\"value\":\"Name 2\"}, {\"value\":\"Value 2\"} ] } ]}";
var wid = "alarms";
postRequest(wid,test);
function postRequest(widget, content) {
var headers = {
'User-Agent': 'Super Agent/0.0.1',
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(content)
}
var options = {
url: 'http://example.com:3030/widgets/'+widget,
method: 'POST',
headers: headers,
}
var pdata = querystring.stringify(content);
console.info(pdata)
console.info(Object.prototype.toString.call(pdata));
var post_req = http.request(options, function() {
});
// post the data
post_req.write(pdata);
post_req.end();
}
Спасибо за любые полезные подсказки (или подсказку, как запустить лихую работу с помощью лихого API, но, насколько я понимаю, это невозможно, поэтому я должен придерживаться этих вызовов API :))
упс, просто посмотрите, что в моем первом фрагменте кода отсутствовала требуемая часть, отредактировал ее. npmjs.com/package/request





Что-то идет не так
var options = {
traditional: true,
url: 'http://example.com:3030/widgets/'+widget,
method: 'POST',
headers: headers,
data: content,
contentType : "application/x-www-form-urlencoded"
}
data не является допустимым ключом в параметрах запроса, это либо тело, либо форма. Это было бы объясните, почему в запросе не отправляются основные данные.
В вашем случае вам нужна форма
form - when passed an object or a querystring, this sets body to a querystring representation of value, and adds Content-type: application/x-www-form-urlencoded header. When passed no options, a FormData instance is returned (and is piped to request). See "Forms" section above.
var options = {
traditional: true,
url: 'http://example.com:3030/widgets/'+widget,
method: 'POST',
headers: headers,
form: content,
contentType : "application/x-www-form-urlencoded"
}
см. https://www.npmjs.com/package/request#requestoptions-callback для более подробной информации.
Argh, rtfm: D Спасибо, я полностью полагался на учебник в Интернете с использованием ключа данных. Так я получу данные, спасибо!
PS: Для варианта использования обновления виджета в Dashing необходимо использовать клавишу «body». На всякий случай кто-то наткнулся на этот вопрос по той же причине, что и я;)
Какую библиотеку запросов вы используете?