Gruntfile.js: Handlling grunt-http callback...ERROR - javascript

I am working on grunt-http.
If I pass an invalid credential then it's throwing an error like:
Running "http:test_grunt_http" (http) task
Fatal error: 401 {"status":"error","errorCodes":["INVALID_CREDENTIALS"],"data":{"message":"Invalid email or password. Please try again."}}
Gruntfile.js
module.exports = function (grunt) {
require('time-grunt')(grunt);
grunt.config.init({
http: {
"test_grunt_http": {
options: {
url: "http://localhost:8000/studentdb/login/auth/",
headers: {
"Accept": "*/*",
"Content-Type": "application/json"
},
method: 'POST',
body: JSON.stringify({
email: 'loginID',
password: 'loginPassword'
}),
callback: function (error, response, body) {
if (response.statusCode === 200) {
var resData = JSON.parse(body);
console.log('body: ', resData);
} else {
console.warn(error); // error is not handling
}
}
}
}
}
});
require('load-grunt-tasks')(grunt);
grunt.loadNpmTasks('grunt-http');
grunt.registerTask('default', ['http', 'func2']);
grunt.registerTask('func2', function (key, value) {
console.log("I am with in function-02");
});
};
run : grunt default
Output:
If I pass a valid credential then both grunt task (http, func2) is working properly. But if I pass a wrong credential then stop grunt file execution at first task execution time. That means 2nd is not executing in this scenario.
Now my question is, how to handle grunt-http callback error?

This issue is resolved.
If add ignoreErrors: true within option, then it's working properly.
options: {
ignoreErrors: true,
. . .
}
But I am not able to print the http-error. Is there any way to capture it?

Related

Sending file to Slack using 'https' in node.js

So I wrote Slack reporter for my automated tests and wanted to switch from deprecated module 'request' to 'https' module. I changed the request sending a normal message but I don't know how to create a request for sending a file. I can't find any example in node documentation (no POST examples for 'https' there) nor any example of that kind of use on the internet. Can anyone help me with this?
That's the working request:
function sendLogFile() {
console.log("Sending log file to slack...");
return new Promise((resolve, reject) => {
request.post(
{
url: fileUploadUrl,
formData: {
token: token,
method: "POST",
title: "Test Log File",
filename: "testLog.txt",
filetype: "auto",
channels: "***",
file: fs.createReadStream("testLog.txt")
}
},
function(err, response) {
if (response.body.includes("created"))
resolve("File send successfully!");
if (response.body.includes("error")) reject(response.body);
if (err) reject(err);
}
);
});
}
And this is kinda (SEE THE EDIT BELOW) what I want (but it's not working):
function sendLogFile() {
return new Promise((resolve, reject) => {
const requestOptions = {
url: fileUploadUrl,
headers: headers,
formData: {
token: token,
method: "POST",
title: "Test Log File",
filename: "testLog.txt",
filetype: "auto",
channels: "***",
file: fs.createReadStream("testLog.txt")
}
};
const req = https.request(requestOptions, res => {
res.on("data", d => resolve(d));
});
req.on("error", e => {
reject(e);
});
// Probably that's the part where I'm stuck:
req.write('????????')
req.end();
});
}
I know there is slackapi for node but the thing is I need this reporter to be without any additional packages. And I know it's possible with request.promise or xhr but I need this to be 'https'.
EDIT:
Ok, so I was trying to get somewhere and I think it should look more like:
const file = fs.createReadStream("testLog.txt");
const options = {
channels: "***",
hostname: "slack.com",
port: 443,
path: '/api/files.upload',
method: 'POST',
headers: {
'Authorization': "Bearer ***",
'Content-Type': 'application/json; charset=utf-8',
}
}
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()
But I have no idea how to past file to req.write(data) since 'data' has to be string, Buffer, ArrayBuffer, Array, or Array-like Object.
So, for now, the response I get is:
statusCode: 200 {"ok":false,"error":"no_file_data"}%
And I'm also not sure if it's possible because slack API says the header should be formData but this response suggests this approach is fine I guess.
Anyone, please?
If you refer to https documentation you can see that options object does not accept such property as formData.
Instead, you should try to send the post data like in this answer.

Google Cloud Functions finishes with: timeout when using Axios

I want to use a Google Cloud Function with a http trigger to write data into a Google Spreadsheet.
The following code is my cloud function:
exports.writeDataMaterialCollection = functions.https.onRequest(
(req, res) => {
if (req.method === "POST") {
console.log(req.body);
res.set("Access-Control-Allow-Origin", "*");
const sheets = google.sheets({ version: "v4" });
var jwt = getJwt();
var apiKey = getApiKey();
var spreadsheetId = "sheetIDxxxxxxxxx";
var range = "A:L";
var row = ["data"];
sheets.spreadsheets.values.append(
{
spreadsheetId: spreadsheetId,
range: range,
auth: jwt,
key: apiKey,
valueInputOption: "RAW",
resource: { values: [row] }
},
(err, result) => {
if (err) {
throw err;
} else {
console.log(result.data.updates.updatedRange);
res.status(200).send(result.data.updates.updatedRange);
}
}
);
}
}
);
When I make a curl POST request, then the data is written to the spreadsheet correctly.
url -d '{"test": "wert"}' -X POST http://localhost:5001/XXXX/writeDataMaterialCollection
Problem
What I don't understand is when I use Axios inside Vue.js, Google Cloud Function returns throw new Error("Function timed out.")
axios(
"http://localhost:5001/XXXXX/writeDataMaterialCollection",
{
method: "POST",
headers: {
"content-type": "application/json",
"Access-Control-Allow-Origin": "*"
},
data: {
daten1: 23
}
}
).then(response => (self.writeDataResult = response));
If your function gets to the point of this line:
throw err;
It will not actually terminate the function and propagate that error to the client. That's because you're throwing an error out of a callback function, not the main function. This also means that function will timeout, because no response is being sent to the client.
What you should do instead is send an error to the client, so the function can correctly terminate, and the client can receive the error. You might want to consider logging the error as well, so you can see in the console what went wrong:
if (err) {
res.send(500);
console.error(err);
}

how to pass value in api body in protractor while requesting the api

I want to pass the value in API request body.
I tried below code for that
var options = { method: 'POST',
url: 'https://ssgpreprod.serviceurl.in/gonogo-api/atm/tw/cro-approval',
headers:
{ 'Postman-Token': '9d6a0ad1-c3a1-402f-b845-b6416f49df6b',
'cache-control': 'no-cache',
'Content-Type': 'application/json' },
body:
{ oHeader:
{ sReqType: 'application/json',
sAppSource: 'WEB 2.02.01',
sSourceID: 'GONOGO_HDBFS',
sAppID: 610961419000670,
dtSubmit: '',
sCroId: 'HDB_TW_CRO#cell.com',
sDsaId: 'default',
sInstID: 4019,
sUserName: 'CHDBTWCRO',
sProduct: 'TW',
sDealerId: '61096' },
sRefID:testData.twPreIpa.twReferenceId,
sAppStat: testData.twCroDetails.twCroDecision,
aCroJustification: [ { sRemark: testData.twCroDetails.twRemark, sSubTo: testData.twCroDetails.twSubjectTo} ],
bApprAmtExist: true,
dApprAmt: testData.twApplyDetails.twLoanAmount,
dItrRt: testData.twCroDetails.twRoi,
dLtv: testData.twCroDetails.twLtv,
aDedupeRefID: [] },
json: true };
request(options, function (error, response, body) {
if (error) throw new Error(error);
browser.logger.info(JSON.stringify(body));
browser.logger.info(JSON.stringify(response));
browser.logger.info('status code is : ' + response.statusCode);
expect(response.statusCode).toBe(200).then(function () {
browser.logger.info('case is approved');
this.logOut(testData);
})
});
I am passing value from xlsx file i.e testData.twPreIpa.twReferenceId but I am getting 422 status code and below output
[2019-05-28 15:42:10.403] [INFO] : - {"title":"Conversion Failed","status":422,"detail":"The content you've sent is probably malformed."}
Also, when I add - browser.logger.info('approved'); above var options it prints on console.. but when I add - browser.logger.info(testData.twPreIpa.twReferenceId);
It gives me error .. ouput displayed -
Failed: Cannot read property 'twReferenceId' of undefined
TypeError: Cannot read property 'twReferenceId' of undefined
While this may not directly answer your question it should be helpful to you.
I worked on a similar framework to what (I assume) yours looks like,some api and some UI validations.
I had a separate class for my API calls which returned some value, sometimes the entire response body. I allowed myself the ability to pass in whatever body I needed as a parameter.
This is an example of the approach I took.
module.exports = class Endpoints {
addSomethingToUser(bearerToken, userId, JSONbody) {
//Function will preform a POST request and return the status code if successful
//Else if will return the body of the response
let endpoint = 'http://myApp.com:9090/api/users/' + userId;
return new Promise((resolve, reject) => {
let options = {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + token,
},
body: JSON.stringify(JSONbody),
};
request(
endpoint,
options ,
function (error, response, body) {
if (!error && (response.statusCode >= 200 && response.statusCode < 300)) {
resolve(response.statusCode);
} else {
console.log('error:', error, response && response.statusCode);
reject(JSON.stringify(response, undefined, 2));
};
}
);
});
};
}
It is called like
let apiCallsFile = require('../apiCalls/restCalls');
let apiCalls = new apiCallsFile();
it('simple test', async function(){
let requiredBody = {
"NAME": "Test Name",
"GENDER": "MALE",
};
let apiResult = await apiCalls.addSomethingToUser(bearerToken, userId, requiredBody );
expect(apiResult).toBe('201');
}
Your issue seems to be related to the actual values you are using from excel. You should attempt to print out your values before attempting to send the request to ensure they are all present and in the format you expect.

Header section has more than 10240 bytes (maybe it is not properly terminated)

I'm using NodeJs to try to upload an attachment to a Jira Issue via the Jira Rest API.
The api expects multipart/form-data so this is how I'm calling it in Node:
function uploadAttachments(supportFormData, callback) {
const url =
'https://somewhere.com/jira/rest/api/2/issue/' +
supportFormData.issueId +
'/attachments';
var options = {
url: url,
headers: {
Authorization: { user: username, password: password },
'X-Atlassian-Token': 'nocheck'
}
};
var r = request.post(options, function(err, res, body) {
if (err) {
console.error(err);
callback(false);
} else {
console.log('Upload successful! Server responded with:', body);
callback(false);
}
});
var form = r.form();
form.append('file', supportFormData.attachments[0].contents, {
filename: supportFormData.attachments[0].fileName,
contentType: supportFormData.attachments[0].contents
});
}
The error I'm receiving is:
org.apache.commons.fileupload.FileUploadException: Header section
has more than 10240 bytes (maybe it is not properly terminated)
The "supportFormData.attachments[0].contents" is ofType Buffer.
Any suggestions as to what could be causing this error?
I ran into this same issue and it turns out JIRA (or Java) requires \r\n as new line character. After I changed \n to \r\n my requests went through without problem.
If its a basic auth change options object to
let auth = new Buffer(`${username}:${password}`).toString('base64');
var options = {
url: url,
headers: {
Authorization: `Basic ${auth}`,
'X-Atlassian-Token': 'nocheck'
}
};

Post request from Scheduled Job is not working

(I am new to JS, node.js and Heroku so I hope the question is clear)
I have an Heroku node.js app, I was able to set up Heroku scheduler to run a task every 1 hour.
The task runs on time and the method fireHook() is called (I can see the log in the console) but the request does not work (I don't get any lo or error).
This is the job:
#!/usr/bin/env node
var request = require('request')
function fireHook(){
console.log("firing")
request({
url: 'https://XXXXXX.herokuapp.com/jobs',
method: "POST",
headers: { "content-type": "application/json" },
json: {"user_id":{ "id":"ddddd"}}
}, function(error, response, body) {
console.log(response)
if (error) {
console.log('Error sending messages: ', error)
} else if (response.body.error) {
console.log('Error: ', response.body.error)
} else {
console.log('success: ', body)
reportToSnitch()
}
})
}
fireHook();
process.exit();
2 questions:
Why sold the request not working ?
I am currently using a webhook to call my main app, is there a better way to call a function on the main app from the script directly?
Thanks
I think your process.exit() is killing your script before the request has received its response. Try to move it into the callback:
#!/usr/bin/env node
var request = require('request')
function fireHook(){
console.log("firing")
request({
url: 'https://XXXXXX.herokuapp.com/jobs',
method: "POST",
headers: { "content-type": "application/json" },
json: {"user_id":{ "id":"ddddd"}}
}, function(error, response, body) {
console.log(response)
if (error) {
console.log('Error sending messages: ', error)
} else if (response.body.error) {
console.log('Error: ', response.body.error)
} else {
console.log('success: ', body)
reportToSnitch()
}
process.exit();
})
}
fireHook();
JavaScript is asynchronous so you have to be careful to consider where and when certain events will occur. If your reportToSnitch() function is async as well, you may need to fire the process.exit() at the end of that function.

Categories