Express Nodejs - How to pass request.files to another POST request - javascript

I have a page where user uploads files and are passed to Node API which does some operations like database insert and finally has to send the files to another node rest API for virus check.
I can see file content and attributes in req.files in the first API call but struggling to pass req.files to another node API URL using request.post.
var uploadFile= function(req, res) {
var files = req.files.upload;
Async.series(
[ function (callback) {..},
function (callback){viruscheck(files,callback);}
....
//viruscheck method
var viruscheck= function(files, callback) {
request.post({url: "http://loclahost:1980/viruscheck/upload.json",
qs: {
..
},
headers: {'enctype-type': 'multipart/form-data'},
form:{
upload:files
}
},function(error, response, body){
if(error) {
console.log(error);
callback(error)
} else {
console.log(response.statusCode, body);
callback()
}
});
}
In API http://loclahost:1980/viruscheck/upload.json I see file content in body rather than req.files.
How can I get the files in request.files in my second API call?

Use:
headers: {'Content-Type': 'multipart/form-data'},
Instead of:
headers: {'enctype-type': 'multipart/form-data'},
enctype is an HTML form thing.
See this answer for more:
Uploading file using POST request in Node.js

Related

Can't get body response with Node from RESTFUL API

I'm tring to get a body response from a RESTFUL API using Node.js and it's "request" lib to send a GET request. Here's the code:
const request = require('request');
const url = 'https://myurl.com';
const headers = {
'x-functions-key': 'mysecretkey'
};
request.get(`${url}${headers}`, (err, response, body) =>{
if (err){
console.log(err)
}
console.log(body)
})
But when I run "node myfile" I get no response from the body, the console return is blank. I think I'm missing something. I've tested the URL and key with Postman and it's working fine, the JSON response appears to me there.
Obs.: I'm new to Node, tried with this tutorial: https://www.twilio.com/blog/2017/08/http-requests-in-node-js.html. The "url" and "key are masked here for security reasons. Any help is fine to me, I'm grateful.
The issue is that you can't just put headers inside the template string. You need to specify them with an options object.
request.get({ url: url, headers: headers }, (err, response, body) => { ... });
Or, with ES6 shorthand:
request.get({ url, headers }, (err, response, body) => { ... });
The problem is that on request.get line you have your URL and headers templates
`${url}${headers}`
Here's the documentation regarding custom headers
So the solution would be creating an options variable like this:
const options = {
url: 'https://myurl.com',
headers: {
'x-functions-key': 'mysecretkey'
}
};
And then passing it to request
request.get(options, (err, response, body) =>{
if (err){
console.log(err)
}
console.log(body)
})
Hope this helps

Retrieve redirectUri from npm Request

I'm trying to retrieve some information from the response that npm Request generated. I'm able to retrieve information like "statusCode" by typing "response.statusCode". However if I want to retrieve other information like "redirectUri", it would show undefined. How am I able to retrieve "redirectUri"?
Below is the code to get the response from the URL that I'm testing;
var request = require('request');
var getRequest = function (url, index) {
request(url, function (error, response, body) {
console.log(response.redirectUri);
});
}
getRequest('https://www.exampleUrl.com', 1);
Below are some of the information from the response;
redirects: [
{ statusCode: 302,
redirectUri:'https://www.exampleurl'.....etc
}],
Please see the response in attached image
Note: I have blurred out the url that I'm testing.
I found my answer from How do I get the redirected url from the nodejs request module?. Set "followRedirect: false" and use "response.headers.location".
var url = 'http://www.google.com';
request({ url: url, followRedirect: false }, function (err, res, body) {
console.log(res.headers.location);
});

How to make a POST request using CustomVision api with NodeJS

I'm trying attach an image using the bot emulator tool and sending this image off to the microsofts customvision api, the issue I'm having is that I get
{ Code: 'BadRequestImageFormat', Message: '' }
back from custom the custom vision api call.
I'm using the the request module from npm to handle the calls
// Receive messages from the user and respond by echoing each message back (prefixed with 'You said:')
var bot = new builder.UniversalBot(connector, function (session) {
session.send("Hello"); //session.message.text
// If there is an attachment
if (session.message.attachments.length > 0){
console.log(session.message.attachments[0])
request.post({
url: 'xxx',
encoding: null,
json: true,
headers: {
'Content-Type': 'application/octet-stream',
'Prediction-Key': 'xxx'
},
body: session.message.attachments[0]
}, function(error, response, body){
console.log(body);
});
}
});
I believe that I may be sending the wrong format through to custom vision however I have been unable to figure it out as of yet.
I replicated your issue and it looks like the problem is your 'Content-Type'. You're attempting to pass JSON in your request, but setting the content-type as octet-stream. See my modified code below:
var bot = new builder.UniversalBot(connector, function (session) {
session.send("Hello"); //session.message.text
// If there is an attachment
if (session.message.attachments.length > 0){
console.log(session.message.attachments[0])
request.post({
url: 'https://northeurope.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures',
encoding: null,
json: true,
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'Your API Key...'
},
body: session.message.attachments[0]
},
function (err, response, body) {
if (err) return console.log(err)
console.log(body);
});
}
});
When I run this, I get the error InvalidImageUrl which is to be expected as it's looking for a content on localhost. You could get round this by exposing your localhost using Ngrok.

Chunked base64 string, piece by piece using http nodejs

From my API(nodejs), I'm accessing a third-party API (using http) to download files.
The service returns a Base64 string, chopped into smaller pieces, to be able to handle larger files.
Is it possible to do multiple http-requests (loop ?) to the third-party service, send each piece in response, to the browser until there is no longer any response from the third-party service?
The reason i want to do this, is because I don't want to consume to much memory on the node server.
I will put the pieces back together in the browser.
Any suggestions on how to do this?
See my current code below.
var request = require('request');
router.post('/getfiledata', function(req, res) {
var fileid = req.body.fileid;
var token = req.headers.authorization;
getFileData(req, res, dbconfig, fileid, token, function(err, chunkOfFile) {
if (err) {
res.status(500).send({
status: 500,
message: err
});
return;
}
res.send(chunkOfFile);
});
});
function getFileData(req, res, dbconfig, fileid, token, next) {
var url ="http://*ip*/service/rest/getfiledata";
var reqbody = {
fileId: fileid
};
var options = {
url: url,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': token
},
json: true,
body: reqbody
};
/*SOME LOOP HERE TO GET EACH CHUNK AND SEND TO BROWSER*/
request(options, function(err, resp, body) {
if (err) {
console.log(err);
next(err, undefined);
return;
} else {
next(undefined, body)
};
});
};
I think you need Socket.io to push chunks to the browser.
Server :
socket.send("chunk", chunkOfFile)
Client :
let fullString = ""
socket.on("chunk", chunkOfFile => fullString += chunkOfFile )
Something like that
The request library you are using allows for streaming of data from one source to another. Check out the documentation on github.
Here is an example from that page:
request
.get(source)
.on('response', function(response) {
console.log(response.statusCode) // 200
console.log(response.headers['content-type']) // 'image/png'
})
.pipe(request.put(destination))
You may choose to use the http module from Nodejs, as it implements the EventEmitter class too.
I ended up doing a recursive loop from the client. Sending http-requests to my API(node) until the response no longer returns any base64 data chunks.
Thank you guys!

Node JS How to POST image along with request data to another server/api

I am trying to POST an image from my Node JS app to another REST API. I have the image in Mongo DB (as binary array data) that is read by Node JS and then is supposed to be POSTed to another API.
The problem I face is how do I send request data along with the image? I have this raw data (that is in JSON format) that should be POSTed along with image:
{"data":{"client":"abc","address": "123"},"meta":{"owner": "yourself","host": "hostishere"}}
I am required to do this using the 'request' module. I can use 'multer' if that helps better. But, I am stuck on how do I send the above request data along with the image stream. Below is my current code. Could you please help me finish it?
var options = {
host: 'hostname.com',
port: 80,
path: '/api/content',
method: 'POST',
headers:{
'Content-Type' : 'multipart/form-data'
}
};
var request = http.request(options, function(response) {
var str = '';
var respTime ='';
response.on('data', function (chunk) {
str = str.concat(chunk);
});
response.on('end', () => {
console.log('No more data in response.');
});
setTimeout(function() {
res.send(JSON.stringify(
{
'imageURL': IMG_URL,
'imageId': IMG_ID,
'body': JSON.parse(str)
}
));
}, 1000);
});
request.on('error', (e) => {
console.error('**** problem with request: ', e);
});
request.write(image.IMG_STR); //image.IMG_STR is the binary array representation of the image.
request.end();
UPDATE: 06/06/2017
So, I happened to talk to the REST team that provides the end point and found out that the data should be sent in the following specific format. Below is a snapshot of the request that succeeded. Could someone help me with the Node code that I should use? I have tried form-data package but have been getting the same error:
if you have control over "the other API" too, you could include the image as base64 representation of the binary data in the post-body (and decode it on the API side)
answer to the update 06/06/2017:
according to the screenshot the API requires multipart/formdata.
such requests with the "request"-module are documented in https://github.com/request/request#multipartform-data-multipart-form-uploads
quick example (not tested):
var formData = {
Data: {data: {client: "abc" ...},
file: fs.createReadStream('testImage_2.jpg'),
};
request.post({url:'<YourUrl>', formData: formData}, function optionalCallback(err, httpResponse, body) {
if (err) {
return console.error('upload failed:', err);
}
console.log('Upload successful! Server responded with:', body);
});
If you add the body to your request with the JSON data, you should be able to send it:
var options = {
host: 'hostname.com',
port: 80,
path: '/api/content',
method: 'POST',
headers:{
'Content-Type' : 'multipart/form-data'
},
body: {
"data": {"client":"abc","address": "123"},
"meta":{"owner": "yourself","host": "hostishere"}
}
};
What I don't understand is why you have a setTimeout with res.send when there is no res variable defined anywhere.

Categories

Resources