how to make post request in inline editor dialogflow? - javascript

First of all,I am using the blaze tier, so no issue of billing.
I have also included
"request" : "*"
in package.json dependencies.
Look at my code index.js in the inline editor:
`
'use strict';
var global_request = require('request');
var myJSONObject = {
"limit": 10,
"offset": 0,
"query": "example"
};
global_request.post(
'https://example.com', {
json: myJSONObject },
function (error, res, body) {
if (!error && res.statusCode == 200) {
console.log(res);
console.log(body);
}
}
);
`
But in the firebase log I am getting the following error:
Unhandled rejection
Error: Can't set headers after they are sent.
I followed How to make an HTTP POST request in node.js? for help. But the code still has errors.
What am I doing wrong here?? Thanks for help.

The Dialogflow library assumes that you're using Promises if you're doing asynchronous operations.
Typically, instead of using the request library, I use the request-promise-native library. So that block of code might look something like this:
var rp = require('request-promise-native');
var myJSONObject = {
"limit": 10,
"offset": 0,
"query": "example"
};
var options = {
method: 'post',
uri: 'https://example.com',
body: myJSONObject,
json: true
};
return rp( options )
.then( body => {
console.log( body );
// This is also where you'd call the library
// to send a reply.
return Promise.resolve( true );
})
.catch( err => {
// You should also return a message here of some sort
return Promise.resolve( true );
});

Related

How to get one item from body API?

I am working on a project that I have to authenticate e get a token from API body content.
How can I Get only the access_token and save it on a variable to use in another API?
I tried too many things to access it. I think it´s something very easy to do, but I don´t know how!
I am new in node/typescript.
Thank you!
Result:
{
"access_token": "eyJhbGciOiJSUzUxMiIAU6l9z2zMQiI9g",
"refresh_token": "AFGpstweytwtewetwetwetwetwetwet2Fg",
"scope": "default",
"token_type": "Bearer",
"expires_in": 3600
}
export const chamada = (event, context, callback) => {
var request = require('request');
console.log('fora');
request.post('http://MY_API',
{ json: { key: 'value' } },
function (error, response, body) {
if (!error && response.statusCode == 201) {
console.log('dentro');
console.log(body);
}
else {
console.log(response.statusCode);
}
}
);
const p = new Promise((resolve) => {
resolve('success');
});
p.then(() =>
callback(null, {
message: 'Go Serverless Webpack (Ecma Script) v1.0! First module!',
event,
})
).catch((e) => callback(e));
};
You have to read the property from the response. Inside of the first if in the callback, you can just access body.access_token and do whatever you like with it.
Not sure I understand what you mean by "use it in another api". Maybe you can add more description on how you want to use it?
By the way, I see that the library that you are using (request) is marked as deprecated, so if possible, you might want to replace it.

Node.js http request returning body/msg empty

I am trying to use the requestjs package to post data and wait for a response. But I the body response is always undefined.
var request = require('request');
request({
method: "POST",
baseUrl: "https://255.255.255",
uri: "/login",
form: {
username: "username",
password: "password",
autologin: "true"}},
function(body, msg, err){
console.log(body); console.log(msg);
})
Edit: Again, the undefined body was caused by a privacy policy.
The format for the callback is (err,response,body); maybe that is why you are getting a empty body and response.
You can refer here for details.
I think you are getting confused with Promise and non-promise request package. As per your example, $ajax returns Promiseified response and you directly get the data from the response of the ajax request. You are expecting that request package should also give you data directly, which is not correct.
Actually, you can solve your issue in two ways:
Sol. 1:
Use proper callback function arguments and you must get data in the third argument of the callback function. Such as:
var request = require('request');
request({
method: "POST",
baseUrl: "https://255.255.255",
uri: "/login",
form: {
username: "username",
password: "password",
autologin: "true"
}
},
function (error, httpResponse, body) {
if (error) {
console.error(error);
}
console.log(httpResponse.statusCode);
console.log(body);
});
Sol. 2:
Use request-promise NPM package (download it from here) and get pomisified response. For example:
var request = require('request-promise');
const getData = async () => {
return new Promise((resolve, reject) => {
const options = {
method: "POST",
baseUrl: "https://255.255.255",
uri: "/login",
form: {
username: "username",
password: "password",
autologin: "true",
resolveWithFullResponse: true, // Returns full response. To get only data don't use this property or mark it false.
}
};
// Get whole Response object.
const response = await request(options);
// Returns the Promise.Resolve or Reject based on response.
if (response.statusCode < 200 || response.statusCode > 300) {
const errorMsg = 'Error occurred while POSTing the request. Got status: ' + response.status;
console.error(errorMsg);
// Reject the promise. Should be caught.
return reject(errorMsg);
}
const responseBody = response.body;
console.log(responseBody);
// Return the response.
return resolve(responseBody);
})
}
Above implementation will return a promise for the method getData() being called.
NOTE: The statement const response = await request(options); will return whole response object if resolveWithFullResponse: true, is used in the options JSON object. If you need only response body or data don't mention resolveWithFullResponse property in the options or assign value false to it. By default the value of resolveWithFullResponse is false.

TypeError: data.filter is not a function

I am trying to filter an array of JSON objects, which I get from an API call on my proxy. I am using a Node.js web framework Express to make the API call.
API returns the following:
{
data: [
{
type: "aaa",
name: "Cycle",
id: "c949up9c",
category: ["A","B"]
},
{
type: "bbb",
name: "mobile",
id: "c2rt4Jtu",
category: ["C","D"]
},
...
]
}
server.js
function sortDataByID(data) {
return data.filter(function(item) {
return item.id == 'c949up9c';
});
}
app.get('/products', (req, res) => {
const options = {
url: BASE_URL + '/products',
headers: {
'Authorization': 'hgjhgjh',
'Accept': 'application/json'
}
}
request.get(options).pipe(sortDataByID(res));
});
I keep getting the following error message.
TypeError: data.filter is not a function
What is the obvious mistake here? Anyone?
I think your mistake is to think than res is the data than you expect.
But if you take a look inside res you should find the data.
so you must get datafrom the res and use it.
For example:
const data = res.data;
request.get(options).pipe(sortDataByID(data))
Have a nice day !
I've personally never seen piping to a function. I don't think that should work. In any case:
You can use a callback instead of piping. Try this:
app.get('/products', (req, res) => {
const options = {
url: BASE_URL + '/products',
json: true, //little convenience flag to set the requisite JSON headers
headers: {
'Authorization': 'hgjhgjh',
'Accept': 'application/json'
}
}
request.get(options, sortDataByID);
});
function sortDataByID(err, response, data){ //the callback must take 3 parameters
if(err){
return res.json(err); //make sure there was no error
}
if(response.statusCode < 200 || response.statusCode > 299) { //Check for a non-error status code
return res.status(400).json(err)
}
let dataToReturn = data.data.filter(function(item) { //data.data because you need to access the data property on the response body.
return item.id == 'c949up9c';
}
res.json(dataToReturn);
}
I received TypeError: data.filter is not a function while doing Unit testing.
I was passing an object not an array in the result.
gateIn$: of({}),
instead of
gateIn$: of([]),
gateIn$.pipe(takeUntil(this.destroy$)).subscribe(bookings => (this.dataSource.data = bookings));
once you see the error it is pretty obvious, the hard bit is spotting it in the first place.

How to post raw body using the npm request package

I want to post a request to a service using the npm request package. The service accepts a request body of comma-separated numbers such as 1,2,3, but when I post the request, the body is "1,2,3" instead, which the service does not recognise. I use the following code:
import request from "request";
export function getIt(numbers) {
return new Promise((resolve, reject) => {
const uri = 'http://foo.bar/getIt';
const numbersBody = numbers.join(',')
console.log('post body: ', numbersBody) // prints 1,2,3
request
.post(
uri,
{ json: true, rejectUnauthorized: false, body: numbersBody },
(err, httpResponse, body) => {
let error = err && err.message ? err.message : err;
if (body && body._error_code) {
error = body.message;
}
if (error) {
reject(error);
} else {
resolve(body);
}
}
)
});
When I inspect the network traffic with Wireshark, I can see that the body becomes "1,2,3". It seems to be because the request package writes it as a json object. I have tried to remove the json: true part of the option, and also tried changing it to false, but that throws an exception. So I don't know how to make the string be the raw body, without the quotation marks. Is there any way to make that happen?

Azure Functions Redirect Header

I want one of my Azure Functions to do an HTTP Redirection.
This is the current code of the function:
module.exports = context => {
context.res.status(302)
context.res.header('Location', 'https://www.stackoverflow.com')
context.done()
}
But it does not work.
A request sent from Postman shows the response has:
Status: 200
Location not set
Is this correct code? Or is it simply not allowed by Azure Functions?
The code above actually does work, unless you have your binding name set to $return, which is what I assume you have now (you can check in the integrate tab)
Either of the following options will also do what you're looking for
Assuming $return in the binding configuration:
module.exports = function (context, req) {
var res = { status: 302, headers: { "location": "https://www.stackoverflow.com" }, body: null};
context.done(null, res);
};
Or using the "express style" API (not using $return in the binding configuration):
module.exports = function (context, req) {
context.res.status(302)
.set('location','https://www.stackoverflow.com')
.send();
};
The following code works for me:
module.exports = function (context, req) {
res = {
status: 302,
headers: {
'Location': 'https://www.stackoverflow.com'
},
body: 'Redirecting...'
};
context.done(null, res);
};

Categories

Resources