I am trying to integrate with a payment gateway in Node and I have successfully been able to post data, but I need to grab the HTTP response status code and store it in a global variable in order to use it for validation.
_doRequest(postData) {
const hostName = XXXXXXXXXXXXXXX;
const path = '/api/transact.php';
postData.security_key = this.security_key;
postData = querystring.stringify(postData);
const options = {
hostname: hostName,
path: path,
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
// Make request to Direct Post API
const req = https.request(options, (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(response.headers)}`);
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
response.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
response.statusCode is what I'm looking to hoist somehow and store in a global variable like const status = statusCode, but I cannot figure out how to accomplish this. I would appreciate any help!
Please try using global.status = statusCode.
You can always access it, while node is running, however this is considered an antipattern.
Related
I am trying to develop a google cloud function that will make an external https GET request and return the response body to the client.
Flow:
client makes request to mockServer function
function makes GET request to example.com
function returns "results" from response body from example.com to client
exports.mockServer = (req, res) => {
'use strict';
var https = require('https');
var options = {
host: 'example.com',
path: '/path',
headers: {
'accept': 'application/json',
'X-API-Key': 'XXXX'
}
};
if (req.method == 'GET'){
https.get(options, function (res) {
var data = '';
res.on('data', function (chunk) {
data += chunk;
});
res.on('end', function () {
if (res.statusCode === 200) {
var res_body = JSON.parse(data);
var results = JSON.stringify(res_body.result)
console.log("results:"+results);
} else {
console.log('Status:', res.statusCode);
}
});
}).on('error', function (err) {
console.log('Error:', err);
});
} else {
console.log("Wrong Method");
}
res.end()
};
I am able to successfully log the results with console.log("results:"+results); but I cannot figure out how to get it returned to the client. I am still new to this and am learning, so thank you so much in advance to any help!
Posting #YouthDev's solution as an answer:
Thanks to #DougStevenson and #Deko in the comments, I switched to an axios library and it works like a charm. Thank you to both for pointing me in the correct direction. Below is the working axios code.
exports.mockServer = (req, res) => {
const axios = require('axios').create({
baseURL: 'https://example.com'
});
return axios.get('/path',{ headers: {'accept': 'application/json','X-API-Key': 'XXXXXX'} })
.then(response => {
console.log(response.data);
return res.status(200).json({
message: response.data
})
})
.catch(err => {
return res.status(500).json({
error: err
})
})
};
I am trying to create a folder for a user, and I have been unsuccessful with api call attempts. My code is able to receive the correct access token, so I believe the be bug would be in createFolderTestFunction below.
async function redirectToDashboard() {
console.log("redirect to dashboard");
// var response = await requestTokenSilent();
var response;
if (!response || !response.status == 200) {
response = await requestTokenPopup();
}
if (response.accessToken) {
console.log(response);
createFolderTest(response.accessToken);
// location.href = hostname;
} else {
console.log("Unable to acquire token");
}
}
function createFolderTest(accessToken) {
var options = {
method: "POST",
headers: {
Authorization: accessToken,
"Content-Type": "application/json"
},
mode: "cors",
body: JSON.stringify({
displayName: "#COOLMONDAY"
})
};
var graphEndpoint = "https://outlook.office.com/api/v2.0/me/Inbox/";
fetch(graphEndpoint, options)
.then(resp => {
console.log(resp);
})
.catch(err => {
console.log(err);
});
}
A recommendation would be to get this working in Graph Explorer first. As this eliminates any issues with language being used and access token permissions.
https://developer.microsoft.com/en-us/graph/graph-explorer/preview
The Microsoft Graph endpoint is actually https://graph.microsoft.com/ , you can use the outlook url but moving forward Graph is where we invest in documentation, sdks and tooling.
As per the documentation https://learn.microsoft.com/en-us/graph/api/user-post-mailfolders?view=graph-rest-1.0&tabs=http
You should be using, you're missing 'mailfolders'
POST /me/mailFolders
You could also use our JavaScript SDK which makes mistakes like these a little easier with intellisense and strongly typed objects.
const options = {
authProvider,
};
const client = Client.init(options);
const mailFolder = {
displayName: "displayName-value"
};
let res = await client.api('/me/mailFolders')
.post(mailFolder);
https://learn.microsoft.com/en-us/graph/api/user-post-mailfolders?view=graph-rest-1.0&tabs=javascript
I am using this example to make a POST API call to an API: https://nodejs.dev/making-http-requests-with-nodejs#perform-a-post-request. No issues there, it works well.
Next, I wanted to create a function that makes this API call by taking in dynamic connection parameters, headers and payload. Did that and I am able to return the response object from the function so I can detect the response.statusCode, response.statusMessage, etc. Here's my Node.js code:
Module Code
const https = require("https");
function postLendingApplication(connection, data, callback) {
const options = {
hostname: connection.hostname,
port: connection.port,
path: connection.path,
method: connection.method,
headers: connection.headers
};
//console.log(options)
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`);
res.on("data", d => {
process.stdout.write(d);
});
callback(res);
});
req.on("error", error => {
console.error(error);
});
req.write(data);
req.end();
}
exports.postLendingApplication = postLendingApplication;
Invoking the code from another file
const bpc = require("./public-api");
const data = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1
});
const connection = {
hostname: 'jsonplaceholder.typicode.com',
port: 443,
path: '/posts',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length,
}
}
var response = bpc.postLendingApplication(connection, data, function(response) {
console.log("Inside the calling function");
//console.log(response);
console.log("Status Code: " + response.statusCode);
console.log("Status Message: " + response.statusMessage);
});
Successful console response
statusCode: 201
Inside the calling function
Status Code: 201
Status Message: Created
{
"title": "foo",
"body": "bar",
"userId": 1,
"id": 101
}
Question: In my callback method, I would like to receive the response body (The JSON) as well as the error so I can run some assertions based on the response/body/error that I received. I am not able to figure out how to setup callback in the module method so it can return all 3 values. If you can please help out with that, it would be greatly appreciated.
Here's the Repl URL in case you'd like to take a stab at it online: https://repl.it/#varun_verma/POST-API
I am not 100% on the question you are asking, I personally if you are wanting to use callbacks in this way use two functions one to handle the error and one for the succsessful response
however, you can use object destruction to give you undefined or default it to null if you like for the item not passed back as shown below:
Module Code
const https = require("https");
function postLendingApplication(connection, data, callback) {
const options = {
hostname: connection.hostname,
port: connection.port,
path: connection.path,
method: connection.method,
headers: connection.headers
};
//console.log(options)
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`);
let data = ''
res.on("data", d => {
data += d;
});
res.on('end', () => {
callback({response: res, data});
});
});
req.on("error", error => {
console.error(error);
callback({response: res, error});
});
req.write(data);
req.end();
}
exports.postLendingApplication = postLendingApplication;
Invoking the code from another file
const bpc = require("./public-api");
const data = JSON.stringify({
title: 'foo',
body: 'bar',
userId: 1
});
const connection = {
hostname: 'jsonplaceholder.typicode.com',
port: 443,
path: '/posts',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length,
}
}
var response = bpc.postLendingApplication(connection, data, function({ response, data, error}) {
// if error is not passed back in the object it defaults to undefined
if (error) console.error(error)
console.log("Inside the calling function");
//console.log(response);
console.log("Status Code: " + response.statusCode);
console.log("Status Message: " + response.statusMessage);
});
If I understand your question correctly, you want to have the response, data, and the error passed to the callback. (where you currently only pass the response)
You can pass the data to the callback like so:
const req = https.request(options, res => {
console.log(`statusCode: ${res.statusCode}`);
let data = '';
res.on("data", d => {
data += d;
});
res.on('end', () => {
callback(res, data);
});
});
This buffers the data from the response as it comes in into a string and then only when the response ends passes both the response object and the data as a string to the callback. (you can then use JSON.parse in the callback to convert the data string to an object)
Passing the error is more difficult as the error callback is given separately from the response. I would recommend having a separate callback for the error:
function postLendingApplication(connection, data, callback, error_callback) {
...
req.on("error", error => {
console.error(error);
error_callback(error);
});
...
}
However someone else on here may be able to give a better solution for the error.
I wold like to know how to make a GET request in node.js sending a body.
const options = {
hostname: 'localhost',
port: 3000,
path: '/abc',
method: 'GET'
}
http.get(options, (res) => {
res.on('data', (chunk) => {
console.log(String(chunk))
})
})
As it says in the documentation:
Since most requests are GET requests without bodies, Node.js provides this convenience method. The only difference between this method and http.request() is that it sets the method to GET and calls req.end() automatically.
So the answer is to use http.request directly. http.request has an example using POST, but it's the same for GET (start the request with http.request, use write to send the body data, use end when done sending data), other than the fact that (as noted above) GET usually doesn't have any body. In fact, RFC 7231 notes that:
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
Using the standard http:
`const http = require('http');
https.get('http://localhost:3000/abc', (resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
console.log(JSON.parse(data).explanation);
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});`
Hope this helps
Using Body in GET request is not recommended at all cause it is not the suggest behavior by HTTP 1.1 but you can use the following method:
const data = JSON.stringify({
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
});
const https = require('https')
const options = {
hostname: 'jsonplaceholder.typicode.com',
port: 443,
path: '/posts',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()
Posting data using net.request is not working. It's reaching the URL. But data not posted. My code is below. Please help me on this.
const net = remote.net;
const querystring = require('querystring');
//**
var postData = querystring.stringify({
'username' : 'test',
'password': 'test'
});
const request = net.request({
method: 'POST',
url: 'http://127.0.0.1/post.php',
});
request.on('error', (error) => {});
request.on('response', (response) => {});
request.write(postData);
request.end();
I know it's been a while. But for the next people who will have the same problem.
Don't forget you must be declare the size of your "postData" in the header.
for example :
var postData = JSON.stringify({"q" : sqlQuery });
const request = net.request({
method: 'POST',
protocol: 'http:',
hostname: '127.0.0.1',
port: 3000,
path: '/select',
headers: {
'Content-Type': 'application/json',
'Content-Length': postData.length
}
})
request.on('response', (response) => {
.... // Something
})
request.write(postData)
request.end()
When using net.request you need to call request.end() after you write your data to assure the request data has been sent.
The reason you need to call request.end() is to allow for changes to be made to the headers and body of your request before you actually make it.
request() will connect and wait for request.end() to send the headers and body in one pass.
Also, it is never a good idea to ignore responses if you want to understand what your code is doing.
You really should hook the request.response event to see what, if any, errors occurred, as in:
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`)
console.log(`HEADERS: ${JSON.stringify(response.headers)}`)
})
Updated - per comment
Your code should read (expanded from example code for net in Electron API Docs):
const request = net.request({
method: 'POST',
url: 'http://127.0.0.1/post.php',
})
let body = ''
request.on('response', (response) => {
// check response.statusCode to determine if the request succeeded
console.log(`STATUS: ${response.statusCode}`)
console.log(`HEADERS: ${JSON.stringify(response.headers)}`)
// capture body of response
// - can be called more than once for large result
response.on('data', (chunk) => {
console.log(`BODY: ${chunk}`)
body += chunk.toString()
})
// when response is complete, print body
response.on('end', () => {
console.log(`BODY: ${body}`)
})
})
request.write(postData)
request.end()