Query ElasticSearch on Node.js with HTTP module Ignores Request Body - node.js

StackOverflow community. I've started to play with ES and Node.js, and right now I'm trying to query my ES instance using the HTTP module.
I'm trying to mimic the following curl GET request:
curl -XGET 'localhost:9200/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query": {
"multi_match" : {
"query": "this is a test",
"fields": [ "subject", "message" ]
}
}
}
'
like this:
var options = {
hostname: '127.0.0.1',
port: 9200,
method: 'GET',
path: '/twitter/tweet/_search?pretty',
headers: {
'Content-Type': 'application/json',
'accept': 'application/json'
},
json: query
body: {
"query": {
"multi_match" : {
"query": "this is a test",
"fields": [ "subject", "message" ]
}
}
}
};
var req = http.request(options, function (response) {
var responseBody = "";
response.setEncoding("UTF-8");
response.on('data', function (chunk) {
responseBody += chunk;
});
response.on("end", function() {
fs.writeFile("responseBody.json", responseBody, function(err) {
if (err) {
throw err;
}
});
});
});
req.on("error", function(err) {
console.log(`problem with request: ${err.message}`);
});
req.end();
But ES is returning ALL the records (like if I was hitting the _all field), not just the hits for the query I'm passing. It's like if the request body is being ignored.
I've also tried to pass it by saving the query in a variable, and the simply put in in the json key:
json: query
But the result is the same. If I enclose the json with single quotes, I get the "unexpected token" error when trying to run the app, so I'm lost on what to do to succesfully pass a query to Node.js with the HTTP module :S.
EDIT:
The solution is to pass the query (JSON stringified) in the request.write method:
req.write(query);
The whole request should look like this:
var query = JSON.stringify({
"query": {
"multi_match" : {
"query": "this is a test",
"fields": [ "subject", "message" ]
}
}
});
var options = {
hostname: '127.0.0.1',
port: 9200,
method: 'GET',
path: '/twitter/tweet/_search?pretty',
headers: {
'content-length': Buffer.byteLength(query),
'Content-Type': 'application/json'
}
};
var req = http.request(options, function (response) {
var responseBody = "";
response.setEncoding("UTF-8");
response.on('data', function (chunk) {
responseBody += chunk;
});
response.on("end", function() {
fs.writeFile("responseBody.json", responseBody, function(err) {
if (err) {
throw err;
}
});
});
});
req.on("error", function(err) {
console.log(`problem with request: ${err.message}`);
});
req.write(query);
req.end();

So the GET request of the http.request won't respect the body, it will always ignore the request body. So, you should send a POST request if you want to send body to the elasticsearch.
The elasticsearch handles both POST and GET call in the same manner.

Related

Issue in creating POST http.request with Node.js data are passed in FormValue instead of Body

i try to execute a http.request POST and my data are passed to FormValue and not in Body.
It's my first experiment in Node.js http calls so I apologize if the question is trivial.
I passed the call to a servere and i got the data at the end of the code.
function doHttpApiCall(session,callback) {
var http = require('http');
var isEndedOk;
var outValue = '';
var postData = JSON.stringify({
grant_type: 'client_credentials',
scope: 'OOB',
my_id: 'my_id_value'
});
var postOptions = {
host: 'dummyapisite.com',
path: '/t/litf9-1571295453/post',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
// Set up the request
var post_req = http.request(postOptions, function(res) {
var statusCode = res.statusCode;
let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
try {
const parsedData = rawData;
if (error) {
isEndedOk = false;
console.error(error.message);
console.error('Response Content=' + String(parsedData));
res.resume();
} else {
isEndedOk = true;
console.log('Response Content=' + String(parsedData));
}
callback(session.attributes,
callBack_doHttpApiCall(outValue, statusCode, session, callback, isEndedOk));
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
post_req.write(postData);
post_req.end();
}
this is the result got by the server and the data are not in the right place.
{
"Timestamp":"2019-10-17T13:53:52.941575Z",
"Method":"POST",
"RemoteAddr":"34.245.148.80",
"ID":390940052,
"Headers":{
"Content-Length":[
"118"
],
"Content-Type":[
"application/x-www-form-urlencoded"
],
"Host":[
"ptsv2.com"
],
"X-Cloud-Trace-Context":[
"deff20a349bfb409fab118aa361ebc54/925376340939905763"
],
"X-Google-Apps-Metadata":[
"domain=gmail.com,host=dummyapisite.com"
]
},
"FormValues":{
"{\"body\":[{\"grant_type\":\"client_credentials\",\"scope\":\"OOB\",\"my_id\":\"my_id_value\"}]}":[
""
]
},
"Body":"",
"Files":null,
"MultipartValues":null
}
The problem is that you're sending a JSON body, but the Content-Type you're sending is: application/x-www-form-urlencoded, so change it to application/json
The server you're posting to, is putting the value in FormValues because you're telling them that you're sending a form (x-www-form-urlencoded)
var postOptions = {
host: 'dummyapisite.com',
path: '/t/litf9-1571295453/post',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': postData.length
}
};

How to add JSON data in a http post request in AWS lambda?

const http = require('http');
exports.handler = function(event, context) {
var url = event && event.url;
http.post(url, function(res) {
context.succeed();
}).on('error', function(e) {
context.done(null, 'FAILURE');
});
};
I am using this in my AWS lambda code to send http request.
I have a JSON file that has to be sent as a part of this post request.
How to add JSON ? Where do I specify ?
If you are asking from where to pickup that json file form, then s3 would be the correct place to put that file and read form the lambda and do a post.
const obj= {'msg': [
{
"firstName": "test",
"lastName": "user1"
},
{
"firstName": "test",
"lastName": "user2"
}
]};
request.post({
url: 'your website.com',
body: obj,
json: true
}, function(error, response, body){
console.log(body);
});
With just http
const postData = querystring.stringify({
'msg': 'Hello World!'
});
const options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
// Write data to request body
req.write(postData);
req.end();

Passing array or nested objects in body of request npm

I have to send some parameters of String type along with one array in my body.
But it throws me an error message:
First argument must be String or buffer
Here is my code:
var tokenList = JSON.parse(req.body.tokenList);
var mobParams = {
"tokens": tokenList,
"profile": "<myprofile>",
"notification": {
"title": req.body.title,
"message": req.body.text
}
};
request({
method: "POST",
url: 'https://api.ionic.io/push/notifications',
headers: {
"content-type": "application/json",
"authorization": "Bearer ********"
},
body: (mobParams)
}, function(error, response, body){
console.log('Ionic push error', error);
console.log('IOnic push res', response);
console.log('IOnic push body', body);
if(!error){
return res.send({
code: 1,
message: "success"
});
}else{
return res.send({
code: 0,
message: error
});
}
How can I pass my array inside this object to request npm?
Also, I would like to add that this implementation works pretty fine through front-end but I have separate codebase which requires me to hit multiple FCM requests i.e. in a loop. So I would be happy to have a solution as neither ionic push nor FCM push works
For the FCM push I am trying the code below :
let desktopParams = {
"notification": {
"title": 'Merchant Portal Notifications',
"body": req.body.text
// "click_action" : action
},
"to": '/topics/' + topic
};
request({
method: "POST",
json: true,
url: 'https://fcm.googleapis.com/fcm/send',
headers: {
"content-type": "application/json",
"authorization": "key=****"
},
body: desktopParams
}, function(error, response, body){
console.log('error', error);
console.log('response', response);
console.log('body', body);
//return body;
});
you should try stringifying your tokenList & req.body.text before you join it with with the string (try to log it and post the outcome so that people will have a better idea about the objects...):
var cho = [{name:'john',lname:'cena'},{name:'mary',lname:'jane'}];
var che = {list:[{name:'john',lname:'cena'},{name:'mary',lname:'jane'}],group:'people'}
var mobParams = {
"tokens":JSON.parse(JSON.stringify(cho)),
"profile": "<myprofile>",
"notification": {
"title": "Some title",
"message":JSON.parse(JSON.stringify(che))
}
};
console.log(JSON.stringify(mobParams));//----->{"tokens":[{"name":"john","lname":"cena"},{"name":"mary","lname":"jane"}],"profile":"<myprofile>","notification":{"title":"Some title","message":{"list":[{"name":"john","lname":"cena"},{"name":"mary","lname":"jane"}],"group":"people"}}}
var arr = [{name:'john',lname:'cena'},{name:'mary',lname:'jane'}]
var js = JSON.stringify(arr);
var blabla = {'item':'something',js}
console.log(blabla); //-----> Object {item: "something", js: "[{"name":"john","lname":"cena"},{"name":"mary","lname":"jane"}]"}
var js = JSON.parse(JSON.stringify(arr));
var blabla = {'item':'something',js}
console.log(blabla); //-----> Object {item: "something", js: Array(2)}
var js = JSON.parse(arr);
var blabla = {'item':'something',js}
console.log(blabla); //-----> "SyntaxError: Unexpected identifier"

Can send post request with curl but cannot from a node server

I can make a post request to a REST api endpoint of a web service with curl successfully but couldnt do so with request module in node.js. Instead, I always get error CONNECTION ETIMEDOUT.What is the problem?
curl command:
curl -i --header "Content-Type: application/json" -XPOST 'http://<endpoint_url>/urls' -d '{
"callback": "http://www.example.com/callback",
"total": 3,
"urls": [ {
"url": "http://www.domain.com/index1.html"
}, {
"url": "http://www.domain.com/index2.html"
}, {
"url": "http://www.domain.com/index3.html"
}
]
}'
code:
function sendRequestToEndPoint() {
const sample = {
"callback": "http://www.example.com/callback",
"total": 3,
"urls": [ {
"url": "http://www.domain.com/index1.html"
}, {
"url": "http://www.domain.com/index2.html"
}, {
"url": "http://www.domain.com/index3.html"
}
]
}
const options = {
method: 'post',
//headers: {
// 'Content-Type': 'application/json',
// 'Accept': 'application/json',
//},
url: 'http://<endpoint_url>/urls',
json: sample
//body: JSON.stringify(sample) // also tried this with headers on
};
console.log(sample);
request(options, (error, response, body) => {
console.log(response)
});
}
Update: Turned out that it was because the api url I used is not correct.
use querystring to stringify your json data,
var querystring = require('querystring');
...
sample = querystring.stringify(sample);
look at this answer How to make an HTTP POST request in node.js
this code works,
you need to Stringify your json object using JSON.stringify , and use the methode write of the object request to send the sample json object
, http = require('http')
, bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
var sample = JSON.stringify({
"callback": "http://www.example.com/callback"
, "total": 3
, "urls": [{
"url": "http://www.domain.com/index1.html"
}, {
"url": "http://www.domain.com/index2.html"
}, {
"url": "http://www.domain.com/index3.html"
}
]
});
var options = {
hostname: 'localhost'
, port: 80
, path: '/test/a'
, method: 'POST'
, headers: {
'Content-Type': 'application/json'
, 'Content-Length': sample.length
}
};
app.get('/', function (req, res) {
var r = http.request(options, (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.setEncoding('utf8');
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
response.on('end', () => {
console.log('No more data in response.');
});
});
r.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
r.write(sample);
r.end();
res.send('ok');
});
a link for more details about http.request nodejs.org http.request(options[, callback])

cURL call to API in NodeJS Request

it's me again with another lame question. I have the following call to a Rattic password database API which works properly:
curl -s -H 'Authorization: ApiKey myUser:verySecretAPIKey' -H 'Accept: text/json' https://example.com/passdb/api/v1/cred/\?format\=json
I tried to replicate this call in NodeJS, however the following returns blank:
var request = require('request');
url='https://example.com/passdb/api/v1/cred/?format=json';
request({
url: url,
method: 'POST',
headers: [
{ 'Authorization': 'ApiKey myUser:verySecretAPIKey' }
],
},
function (error, response, body) {
if (error) throw error;
console.log(body);
}
);
Any help is appreciated.
As pointed out in the comments already, use GET, not POST;
headers should be an object, not an array;
You're not adding the Accept header.
All combined, try this:
request({
url : url,
method : 'GET',
headers : {
Authorization : 'ApiKey myUser:verySecretAPIKey',
Accept : 'text/json'
}, function (error, response, body) {
if (error) throw error;
console.log(body);
}
});
One thing you can do is import a curl request into Postman and then export it into different forms. for example, nodejs:
var http = require("https");
var options = {
"method": "GET",
"hostname": "example.com",
"port": null,
"path": "/passdb/api/v1/cred/%5C?format%5C=json",
"headers": {
"authorization": "ApiKey myUser:verySecretAPIKey",
"accept": "text/json",
"cache-control": "no-cache",
"postman-token": "c3c32eb5-ac9e-a847-aa23-91b2cbe771c9"
}
};
var req = http.request(options, function (res) {
var chunks = [];
res.on("data", function (chunk) {
chunks.push(chunk);
});
res.on("end", function () {
var body = Buffer.concat(chunks);
console.log(body.toString());
});
});
req.end();
Headers should be an object.
var request = require('request');
url='https://example.com/passdb/api/v1/cred/?format=json';
request({
url: url,
method: 'POST',
headers: {
'Authorization': 'ApiKey myUser:verySecretAPIKey'
}
}, function (error, response, body) {
if (error) throw error;
console.log(body);
});

Resources