I have a node instance using express. It makes call to a JAVA backend. When I receive the response I check if there is a content-disposition header and react accordingly with the type of file.
The content of the response.body is the pdf in binary content. With content-type header "application/pdf;charset=UTF-8". I also receive a Content-Transfer-Encoding header set to binary.
If I call my JAVA backend directly from a REST client, everything is fine and I can view the raw body or download the file.
If I go with node, the PDF is blank. But has the correct number of pages.
Here's how I forward the respond to the frontend.
res.status(response.statusCode).set('content-disposition', response.contentDisposition).set('Content-Type', response.contentType).send(response.body);
Is it possible Express is converting it to some default encoding before I can even have access to the response ?
All I want to do is take the body response from my java backend ajust the headers and send it back to the frontend.
Thank you
EDIT
This is the options I pass to my request function
method=GET, user=username, pass=password, uri=http://appsjava-veo01.hostname:8081/VEO/r/pap/pap5001/produire/311, Content-Type=*/*, Accept=*/*
Calling my http handler, and in the callback sending back the response
httpRequest(options, req, res, function(err, response){
if (err){
return next(err);
}else{
if (response.jsonResponse){
res.status(response.statusCode).set('Content-Type', 'application/json').send(response.jsonResponse);
}else{
if (response.contentDisposition){
res.status(response.statusCode).set('Content-Disposition', response.contentDisposition).set('Content-Type', response.contentType).send(response.messageHtml);
}else {
res.status(response.statusCode).set('Content-Type', 'application/json').send(JSON.stringify({
success: response.success,
message: response.message,
messageHtml: response.messageHtml,
dateJour: response.dateJour,
usager: response.usager
}));
}
}
}
});
var httpRequest = function(options, req, res, callback) {
var errorMsg, dateJour;
ASQ(function (done) {
request(options, function (error, response) {
if (!response) {
done.fail(error);
} else {
done(response);
}
});
})
.then(function (done, response) {
var bodyResponse,
httpResponse,
jsonResponse,
contentDisposition = response.headers['content-disposition'],
usager = (req.session.cas) ? req.session.cas.user : 'nocas';
dateJour = new Date().toJSON();
//Validation et aiguillage selon les status code http
if (response.statusCode === 401) {
req.session.pt = '';
httpResponse = {
'statusCode': 401,
'success': false,
'message': '401 - Authorization requise',
'messageHtml': response.body,
'dateJour': dateJour,
'jsonResponse': null,
'usager': usager
};
return callback(null, httpResponse);
} else if (response.statusCode.toString().charAt(0) === '2' || response.statusCode === 406 || response.statusCode === 428) {
if (contentDisposition) {
var contentType = utils.extractContentType(contentDisposition);
httpResponse = {
'statusCode': response.statusCode,
'success': true,
'message': 'Téléchargement du fichier',
'messageHtml': response.body,
'dateJour': dateJour,
'jsonResponse': null,
'contentDisposition': contentDisposition,
'contentType': contentType,
'usager': usager
};
return callback(null, httpResponse);
...................
Related
I am trying to upload an image file from my node.js application to a group's drive in Sharepoint.
As the official documentation states, I'm making my request as follows:
PUT /groups/{group-id}/drive/items/{parent-id}:/{filename}:/content
With the binary image in the body: "The contents of the request body should be the binary stream of the file to be uploaded."
The problem is that the image is uploaded but as a corrupted file. I tried different solutions and still don't see why is always the image corrupted.
Here is my code:
//i get my image from a URL first
https.get(url.parse(attachment.contentUrl), function (response) {
var data = [];
response.on('data', function (chunk) {
data.push(chunk);
});
response.on('end', function () {
if (response.statusCode === 200) {
var buffer = Buffer.concat(data);
//store my image in a local file to test if image is correct (which it is)
fs.writeFile(localFileName, buffer, (fsError) => {
//error handling
});
functions.uploadImageToSharepoint(session, localFileName, buffer,
function (err, body, res) {
if (err) {
console.error(err);
}else{
console.log('OK!');
}
});
} else {
//error handling
}
});
}).on('error', function (e) {
console.log("error2: " + e);
});
//and the request to graph api
function uploadImageToSharepoint(session, fileName, data, callback) {
var options = {
url: 'https://graph.microsoft.com/v1.0/groups/xxxxxxx/drive/root:/yyyyyy/fileName.jpg:/content',
method: 'PUT',
body: data,
json: true,
headers: {
'Content-Type': 'image/jpg',
Authorization: 'Bearer ' + session.userData.accessToken
}
};
request(options, function (err, res, body) {
if (err) return callback(err, body, res);
if (parseInt(res.statusCode / 100, 10) !== 2) {
if (body.error) {
return callback(new Error(res.statusCode + ': ' + (body.error.message || body.error)), body, res);
}
return callback(err, body, res);
}
callback(err, body ,res);
});
}
The file is most likely getting corrupted due to the following option for request:
var options = {
json: true, //<--setting this option sets body to JSON representation of value
//another properties are omitted for clarity
};
In that case request sets body to JSON representation of value and adds accept header to application/json for Upload endpoint and binary file get corrupted.
The solution would be to omit json option from a request and use the proper content-type only:
var options = {
url: '/me/drive/root:/filename.jpg:/content',
method: 'PUT',
body: data,
headers: {
'Content-Type': 'image/jpg',
Authorization: 'Bearer ' + accessToken
}
};
Iam using request() in node js to call external apis.
if (req.method == 'GET')
options.qs = req.query;
else
options.form = req.body;
request(options, function(error, response, body) {
if (error || [constants.response_codes.success, constants.response_codes.internal_server_error, constants.response_codes.error, constants.response_codes.unauthorized].indexOf(response.statusCode) < 0) return next(true);
return next(null, { statuscode: response.statusCode, data: response.body });
});
It is working with req.method GET,POST,PUT and DELETE.But I need to send multipart/form-data for sending files from the client side to laravel project via node js.Iam using body-parser in node js for parsing the request.How can it be achieved by using request() in node js to send file.
You can try this
const options = {
method: "POST",
url: "Your URL",
port: 443,
headers: {
"Authorization": "Basic " + auth,
"Content-Type": "multipart/form-data"
},
formData : {
"image" : fs.createReadStream("./images/src.png")
}
};
request(options, function (err, res, body) {
if(err) console.log(err);
console.log(body);
});
I am using node js request to retrieve the HTML from the following URL but the body is returning empty.
var request = require("request");
var url = 'http://www.topshop.com/en/tsuk/product/bags-accessories-1702216/scarves-465/feather-wings-5884878?bi=0&ps=20';
request({
uri: url
}, function (error, response, body) {
console.log(body);
if (response.statusCode != '200') {
console.log('fail');
console.log(response.statusCode + ' # ' + error);
} else {
console.log(response.statusCode);
console.log('############');
console.log(response);
}
});
On closer inspection I can see this in the response:
_header: 'GET /webapp/wcs/stores/servlet/CatalogNavigationSearchResultCmd?langId=-1&storeId=12556&catalogId=33057&beginIndex=1&viewAllFlag=false&pageSize=20&searchTermScope=3&searchTermOperator=LIKE&searchType=ALL&sort_field=Relevance&searchTerm=TS19M11KRED&x=25&y=11&geoip=search HTTP/1.1\r\nreferer: http://www.topshop.com/en/tsuk/product/bags-accessories-1702216/scarves-465/feather-wings-5884878?bi=0&ps=20&geoip=prod\r\nhost: www.topshop.com\r\nConnection: close\r\n\r\n',
_headers:
{ referer: 'http://www.topshop.com/en/tsuk/product/bags-accessories-1702216/scarves-465/feather-wings-5884878?bi=0&ps=20&geoip=prod',
host: 'www.topshop.com' },
Which I assume means that there has been a redirect? Even though its returned a 200 OK instead of a 302 redirect.
I'm not sure of the best way to retrieve the body from the redirect? Do I need to make another request to the URL in the header? But shouldn't the response code be a 302 in this case instead of a 200?
Any help appreciated.
What you show seem like something that happened after a redirect - see that the referer is set to your original URL.
Maybe you should set more headers, like User-Agent because some servers don't respond without it.
For example, see the code that I wrote for this answer:
'use strict';
var request = require('request');
var url = 'https://api.github.com/users/rsp';
request.get({
url: url,
json: true,
headers: {'User-Agent': 'request'}
}, (err, res, data) => {
if (err) {
console.log('Error:', err);
} else if (res.statusCode !== 200) {
console.log('Status:', res.statusCode);
} else {
// data is already parsed as JSON:
console.log(data.html_url);
}
});
It returns:
https://github.com/rsp
Note that it doesn't work without the User-Agent header:
'use strict';
var request = require('request');
var url = 'https://api.github.com/users/rsp';
request.get({
url: url,
json: true,
}, (err, res, data) => {
if (err) {
console.log('Error:', err);
} else if (res.statusCode !== 200) {
console.log('Status:', res.statusCode);
} else {
// data is already parsed as JSON:
console.log(data.html_url);
}
});
It returns:
Status: 403
The same URL, the same code - the only difference is the User-Agent header.
I've a simple express server responding to one post request:
app.post('/reportFiles', getReportLink);
The server is going to make a post request on another server then save the result into a json file.
But it seems to be not working when i make multiple request. If I call 2 times my express server and the request to the other server are slow, I'll get the result of my first request but never my second (request are the same, just called 2 times).
Here is my code for the function getReportLink:
function getReportLink(req,res){
var params = req.body;
// Send 200 response -> Doing the job in background
respond(res,200,'OK');
var json;
var requestName = params.requestName;
var sessionId = params.sessionId;
var startDate = params.startDate;
var endDate = params.endDate;
var customerId = params.customerId;
var uaid = params.uaid;
var jsonFileName = requestName+'_'+customerId+'_'+uaid+'_'+unix()+'.json';
var platformUrl = require(current_path+path.sep+'platform').getPlatformUrl(config.environment);
async.series([
// Call getrequestName on spring-ws
function(callback){
var requestBody = {sessionId:sessionId,asynch:false,startDate:startDate,endDate:endDate,formatedForTimezone:true,timeZoneOffset:timeZoneOffset};
var reportParams = params;
_.each(_.keys(reportParams), function (key) {
if(key==='reportType' && reportParams[key]<=0){
// We don't add it
}else{
requestBody[key] = reportParams[key];
}
});
logger.debug(jsonFileName);
logger.debug(requestBody);
request({
uri: platformUrl+'get'+reportParams.requestName,
method: 'POST',
json: true,
timeout: 600000,
headers: {'content-type': 'application/json'},
body: requestBody},
function(error, response, body) {
if(!_.isUndefined(response)){
logger.debug(jsonFileName);
logger.debug('Response: '+ response.statusCode);
}
if (error || response.statusCode == 500) {
logger.debug(jsonFileName);
logger.error(error);
logger.debug('Received:'+JSON.stringify(body));
if(!_.isUndefined(returnUrl) && returnUrl){
return respond(res,500, 'Error when getting ressource');
} else {
return logger.error('Error when getting ressource');
}
} else {
json = body;
if( _.isUndefined(json) || _.isNull(json)){
logger.debug(jsonFileName);
logger.debug('Received:'+JSON.stringify(json));
if(!_.isUndefined(returnUrl) && returnUrl){
return respond(res,500, 'Error when getting ressource - not a json object');
} else {
return logger.error('Error when getting ressource - not a json object');
}
} else {
logger.debug(jsonFileName+' : '+' OK go to next');
callback(null, 'getReportName');
}
}
});
},
// Save Json on filesystem
function(callback){
logger.debug(jsonFileName+' : '+' Saving on disk');
if(_.isUndefined(json)){
logger.error('Json is undefined...');
}
fs.writeFile(jsonFileName, JSON.stringify(json), 'utf8', function (err) {
if (err) return logger.error(params);
callback(null, 'writeJson');
});
}
]);
}
Solved this using node-fetch.
Code instead of request now looks like this:
fetch(uri, { method: 'POST', body: JSON.stringify(requestBody), timeout: 600000, headers: {'content-type': 'application/json'} })
.then(function(response) {
logger.debug('Response: '+ response.status + ' ok?'+response.ok);
if (!response.ok) {
logger.debug('Received: '+response.statusText);
return respond(res,500, 'Error when getting ressource. Status='+response.status);
} else{
json = response.json();
if( _.isUndefined(json) || _.isNull(json)){
return respond(res,500, 'Error when getting ressource');
} else {
callback(null, 'getReportName');
}
}
});
SO using curl I can successfully send post request to slack
curl -X POST --data-urlencode 'payload={"channel": "#tech-experiment", "username": "at-bot", "text": "This is posted to #general and comes from a bot named webhookbot.", "icon_emoji": ":ghost:"}' https:/company.slack.com/services/hooks/incoming-webhook?token=dddddddd2342343
however when I converted it to code using nodejs
var request = require('request');
var http = require('http');
var server = http.createServer(function(req, response){
response.writeHead(200,{"Content-Type":"text/plain"});
response.end("end");
});
option = {
url: 'https://company.slack.com/services/hooks/incoming-webhook?token=13123213asdfda',
payload: '{"text": "This is a line of text in a channel.\nAnd this is another line of text."}'
}
request.post(
option,
function (error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body)
}else {
console.log('wtf')
console.log(response.statusCode)
console.log(response)
console.log(error)
}
}
);
it throws status 500. can anyone help?
i reviewed the token
also done my research but nothing is working..
I appreciate all your help
You need to use the https library, since the server requests are on a different port. You current code is sending the request to port 80 instead of port 443. This is some sample code I built for an integration.
var https = require( 'https' );
var options = {
hostname : 'company.slack.com' ,
path : '/services/hooks/incoming-webhook?token=rUSX9IyyYiQmotgimcMr4uK8' ,
method : 'POST'
};
var payload1 = {
"channel" : "test" ,
"username" : "masterbot" ,
"text" : "Testing the Slack API!" ,
"icon_emoji" : ":ghost:"
};
var req = https.request( options , function (res , b , c) {
res.setEncoding( 'utf8' );
res.on( 'data' , function (chunk) {
} );
} );
req.on( 'error' , function (e) {
console.log( 'problem with request: ' + e.message );
} );
req.write( JSON.stringify( payload1 ) );
req.end();
I think it is not payload but form.
This code succeed in calling Incoming Webhooks.
var request = require('request');
var options = {
uri: "https://hooks.slack.com/services/yourURI",
form: '{"text": "This code..."}'
};
request.post(options, function(error, response, body){
if (!error && response.statusCode == 200) {
console.log(body.name);
} else {
console.log('error: '+ response.statusCode + body);
}
});
wanted to chime in, as I found this while also trying to do the same thing. I ended up doing this:
got('https://hooks.slack.com/services/[your configured url]', {
method: 'POST',
body: JSON.stringify({
"text": "message" + variable
})
});
Either use form in your option object or set a body parameter along with the 'content-type' set to 'application/x-www-form-urlencoded'. Here's a working example.
var payload = JSON.stringify(payload)
request.post({
headers: {'content-type' : 'application/x-www-form-urlencoded'},
url: 'Your Webhook URL',
body: "payload="+payload
}, function(error, response, body){
if(error){
console.log(error);
}
console.log(body);
});