I'm trying to pipe a request handling by a remote server, along with the following line:
Unfortunately pipe doesn't work well with post body, could you suggest how can I solve this issue?
self.downloadPriceLists = function (req, res, next) {
const options = {
url: `http://${env.MAILER_HOST}:${env.MAILER_PORT}/getpricelist/`,
method: 'POST',
json: true, // <--Very important!!!
headers: req.headers,
headers: {
'Content-Type': 'application/json;charset=UTF-8',
"Access-Control-Allow-Origin": "*",
},
body: {
userID: req.user.id,
exportAsOf: req.body.exportAsOf,
activationDate: req.body.activationDate,
},
};
console.log("options:", options);
// remoteResponse :: res
// remoteBody :: body
const myReq = request.post(options, function (error, remoteResponse, remoteBody) {
res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition');
remoteResponse.headers.hasOwnProperty('content-disposition') && res.setHeader('Content-disposition', remoteResponse.headers['content-disposition']);
remoteResponse.headers.hasOwnProperty('content-type') && res.setHeader('Content-type', remoteResponse.headers['content-type']);
if (error) {
console.error('request fail:', error);
return res.status(500).end('Error');
}
console.log('submit successful:', remoteResponse.headers);
res.pipe(remoteBody);
});
// Handle errors
myReq.on('error', function (err) {
console.log("++++++++++++sendReq Handle errors:", err);
res.status(500).end("Error:" + err);
});
};
Should you not be piping streams and not scalar data?
res.pipe(remoteBody); does look right to me, if anything, res.pipe(remoteResponse); seems more right.
Have you considered just writing the response of the inner request to the outer one without piping? Like so res.json(remoteBody); ?
Related
I know it's possible to get data sent by the user in the back-end using Express.js which is:
router.get("/pathName", async function(req, res){
count = req.body;
})
But how to do this in vanilla (pure) Node.js itself?
Here's an example of a simple server.
const http = require('http');
http
.createServer((req, res) => {
res.writeHead(200, {
'Content-Type': 'text/html',
});
switch (req.url) {
// http://localhost:8080/
case '/':
res.write('<h1>Home</h1>');
break;
// http://localhost:8080/page
case '/page':
res.write('<h1>Page</h1>');
break;
}
res.end();
})
.listen(8080);
Also, here's an example (probably incomplete in terms of all edge cases...) of getting JSON data from a request payload:
const http = require("http");
// server that only supports POST /count
// expects JSON data to be passed like { "count": 100 }
// must have application/json content type header and POST method
http
.createServer(async (req, res) => {
// ensure method is content type json, POST, and /count
if (
req.headers["content-type"] != "application/json" ||
req.url !== "/count" ||
req.method !== "POST"
) {
res.writeHead(404, {
"Content-Type": "application/json",
});
res.write(JSON.stringify({ message: "Unsupported route" }));
res.end();
}
// try to read body
let body;
try {
body = await readBody(req);
} catch (err) {
res.writeHead(400, {
"Content-Type": "application/json",
});
res.write(JSON.stringify({ message: err.message }));
res.end();
}
// try to parse body
let parsedBody;
try {
parsedBody = JSON.parse(body);
} catch (err) {
res.writeHead(400, {
"Content-Type": "application/json",
});
res.write(JSON.stringify({ message: err.message }));
res.end();
}
// make sure count property is present in parsed body
if (typeof parsedBody.count === "undefined") {
res.writeHead(400, {
"Content-Type": "application/json",
});
res.write(JSON.stringify({ message: err.message }));
res.end();
}
// create response
res.writeHead(200, {
"Content-Type": "application/json",
});
res.write(JSON.stringify({ message: "Got " + parsedBody.count }));
res.end();
})
.listen(8080);
function readBody(req) {
return new Promise((res, rej) => {
let body = "";
req.on("data", (data) => {
body += data;
});
req.on("end", () => {
res(body);
});
req.on("error", (err) => {
rej(err);
});
});
}
Cool to see how it works for learning. But if you're using it for a project, I'd highly recommend Express or another framework/lib as you'll find it will get quite painful to try to consider all various cases you will need. Frameworks like Express are quite light anyway.
I am facing some issue while downloading file using node.js. I have scenario like my angular component is sending the file request. in my first node server I am doing the token validation and then redirecting to another node server where actually the execution happens. I am explaining my code below.
service.ts:
submitAndDownloadFile(formdata : any ){
const token = localStorage.getItem('token')
let headers = new HttpHeaders({
Authorization: 'Basic ' + token
})
const cecID = localStorage.getItem('cec');
const AppUrl = `${environment.nodeJsBaseUrl}:${environment.hostingNodeJsContainerPort}/convert-test-cases/${cecID}`;
return this.httpClient.post(AppUrl, formdata, { responseType: 'blob', observe : 'response', headers : headers});
}
Here I am sending the request to my first node.js server which code has given below.
app.js(first:port-8000):
router.post('/convert-test-cases/:id', middleware.auth, (req, res) => {
try{
let postRequestOptions = {
url: '',
method: 'POST',
json: true,
headers: {},
body: {},
};
postRequestOptions.url = 'http:localhost:9000/convert-test-cases';
postRequestOptions.headers = {
'Content-Type': 'application/json',
};
postRequestOptions.body = req.body;
request(postRequestOptions, async (error, response, pathList) => {
if(error) {
console.log('error', error);
}else{
res.send(pathList);
}
})
}catch(e){
responseObj = {
status: 'error',
msg: 'Error occurred while processing your request',
body: null
}
return res.send(responseObj);
}
})
Here I am doing the token validation using middleware.auth and sending same request to another node.js file which code is explained below.
app.js:(second-port-9000):
router.post('/convert-test-cases', async (req, res) => {
try{
let response = await ctcCtrl.convertTestCase(req.body, req.files);
if(response.status == 'success'){
res.set('Access-Control-Expose-Headers','*, Content-Disposition');
return res.download(response.fileName,response.fileName);
}else{
return res.send(response);
}
}catch(e){
responseObj = {
status: 'error',
msg: 'Error occurred while processing your request',
body: null
}
return res.send(responseObj);
}
})
Here only I am doing some execution and downloading the file. If I am connecting angular to node-9000 its working fine but my requirement is first I have to connect to port-8000 to some token validation and after that I have to send same req.body and re.file to app.js which is running in 9000 using request module. As per my code its not working at all.
I have to take data from my form in my front end code and upload the data to another server using API calls, which I am unable to do right now. I have tried numerous ways and tricks mentioned over the internet to solve the problem faced while uploading a file in NodeJs using Request and Axios but none of them are working for just this particular case and I don't know why.
Here is the code in my client-side if we use Axios:
app.post('/job/addjob', upload.any(), (req, res) => {
console.log(req.files[0].path);
var form = new formData();
form.append('Title', req.body.Title);
// form.append('Services', JSON.stringify(req.body.Services));
form.append('Startdate', req.body.Startdate);
form.append('NoOfPositions', req.body.NoOfPositions);
form.append('EndDate', req.body.EndDate);
form.append('Experience', req.body.Experience);
form.append('Rate', req.body.Rate);
form.append('Location', req.body.Location);
form.append('Description', req.body.Description);
// form.append('Questions', JSON.stringify(req.body.Questions));
form.append('Dresscode', fs.createReadStream(req.files[0].path));
axios({
method: 'post',
url: 'http://13.127.239.92:3000/job/addjob',
data: form,
headers: {'Content-Type': 'multipart/form-data', 'Authorization': req.session.verifiedToken}
}).then(function (response) {
console.log(response.data);
res.redirect('/provider');
})
.catch(function (err) {
//handle error
console.log(err);
res.redirect('/profile/getProfile');
});
});
for which the error that I face is
Error Uploading Image.
And here is the code in my client-side if we use Request:
app.post('/job/addjob', upload.any(), (req, res) => {
console.log(req.files);
var options = {
'method': 'POST',
'url': 'http://13.127.239.92:3000/job/addJob',
'headers': {
'Content-Type': 'multipart/form-data',
'Authorization': req.session.verifiedToken
},
formData: {
'Title': req.body.Title,
// form.append('Services', JSON.stringify(req.body.Services));
'Startdate': req.body.Startdate,
'NoOfPositions': req.body.NoOfPositions,
'EndDate': req.body.EndDate,
'Experience': req.body.Experience,
'Rate': req.body.Rate,
'Location': req.body.Location,
'Description': req.body.Description,
// form.append('Questions', JSON.stringify(req.body.Questions));
'Dresscode1': fs.createReadStream(req.files[0].path),
}
};
request(options, function (error, response) {
if (error) { console.log(error) }
else {
console.log(response.data);
res.redirect('/provider');
}
});
});
for which the error that I face is:
{ Error: socket hang up
at createHangUpError (_http_client.js:323:15)
at Socket.socketOnEnd (_http_client.js:426:23)
at Socket.emit (events.js:203:15)
at endReadableNT (_stream_readable.js:1145:12)
at process._tickCallback (internal/process/next_tick.js:63:19) code: 'ECONNRESET' }
This is the fraction of code from the server-side which might come in handy understanding my problem:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'dresscodes/')
},
filename: function (req, file, cb) {
let uuid=v4();
cb(null, uuid +"."+mime.getExtension(file.mimetype))
pp= uuid +"."+mime.getExtension(file.mimetype);
}
});
let upload = multer({ storage: storage }).any();
upload(req,res,function(err) {
if(err) {
console.log(err);
return res.end("Error uploading image.");
} else{
var fullUrl = req.protocol + '://' + req.get('host') ;
Now to the worst part, I can only make changes to my client-side code and not to the server-side code
I have 2 Nodejs Server running. One of the server just has a post route:
app.post("/",(req,res)=>{
console.log(`Someone sent a post request`)
})
This server is running on localhost:9000. How do I fire the post route from a different Nodejs Server?
You could try something similar to this:
var request = require("request");
app.post("/", (req, res) => {
var options = {
method: 'POST',
url: 'http://localhost:9000/employee',
headers: { 'Content-Type': 'application/json' },
body: { id: 1 },
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
// Process the body and return the response.
return res.send(body);
});
});
Additional link
I was using Azure Speech rest api. And i tried it on post man with a .wav file and it successfully return the result. However, when i call api from my node.js code. It always return Unsupported Audio Format even though i give the same audio file. Can anyone tell me what's the difference of them? Or what did Postman do to make it work?
Below is how i call speech api by node.js.
'use strict';
const request = require('request');
const subscriptionKey = 'MYSUBSCRIPTIONKEY';
const uriBase = 'https://westus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=en-US';
const options = {
uri: uriBase,
body: 'speech.wav',
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key' : subscriptionKey,
'Transfer-Encoding': 'chunked',
'Expect': '100-continue',
'Content-type':'audio/wav; codec=audio/pcm; samplerate=16000'
}
};
request.post(options, (error, response, body) => {
if (error) {
console.log('Error: ', error);
return;
}
let jsonResponse = JSON.stringify(JSON.parse(body), null, ' ');
console.log('JSON Response\n');
console.log(jsonResponse);
});
You can try this
fs.readFile('/path/to/my/audiofile.wav', function (err, data) {
if (err) throw err;
var options = {
host: 'https://westus.stt.speech.microsoft.com/speech/recognition/conversation/cognitiveservices/v1?language=en-US',
method: 'POST',
headers: { 'Content-Type': 'audio/wav' }
};
var req = http.request(options, function(res) {
// Handle a successful response here...
});
req.on('error', function(e) {
// Handle an error response here...
});
// Write the audio data in the request body.
req.write(data);
req.end();
});