How to pass multipart request from one server to another in NodeJS? - node.js

I have two nodeJS servers,
Server 1 gets requests from the client and passes it to server 2 which returns a response to server 1 and it responds to the client.
The client uploads a file and it has to be passed the same way as any other rest request that I have.
I use axios on server 1 to send the data to server2 and multer on server 2 to store the file on disk.
I have an issue sending the request from server1 to server2 because the body of the request contains nothing and the request is Multipart.
How should I handle the request on Server 1 ???
router.post('/fileUpload', (req, res) => {
console.log(req.body);
res.status(200).json({ msg: "Got file" });
});

You can use form-data module to send multipart/form-data from nodejs application
Here is the code you can implement on Server1 to receive image file from client and send it to Server2.
const express = require("express");
const app = express();
const bodyParser = require('body-parser');
var multer = require('multer')();
const FormData = require('form-data');
const axios = require('axios');
const fs = require('fs');
app.use(bodyParser.json());
app.post('/fileUpload' , multer.single('fileFieldName'), (req , res) => {
const fileRecievedFromClient = req.file; //File Object sent in 'fileFieldName' field in multipart/form-data
console.log(req.file)
let form = new FormData();
form.append('fileFieldName', fileRecievedFromClient.buffer, fileRecievedFromClient.originalname);
axios.post('http://server2url/fileUploadToServer2', form, {
headers: {
'Content-Type': `multipart/form-data; boundary=${form._boundary}`
}
}).then((responseFromServer2) => {
res.send("SUCCESS")
}).catch((err) => {
res.send("ERROR")
})
})
const server = app.listen(3000, function () {
console.log('Server listening on port 3000');
});
Here multer is used to handle the uploaded file

const formData = new FormData();
formData.append('query', updateDocQuery);
formData.append('variables', JSON.stringify(this.setUpdateDocParams() || {}));
for (let i = 0; i < fileArr.length; i++) {
formData.append(`file${i}`, fileArr[i])
}
you can append your query variables and file to formData and pass formData to body

Related

How can a TCP/IP server write data on a HTTP server?

Here is my tcp/ip server that listens to IoT sensors sending it data:
const net = require('net')
const server = net.createServer(socket => {
socket.on('data', data => {
console.log(data.toString())
})
}).listen(1234)
I receive the data fine. A line of data received looks like 'DATA,zoneA,20'.
Now I want to write that stream of data to this http server:
const express = require('express')
const morgan = require('morgan')
const app = express()
const bodyParser = require('body-parser')
const {PORT} = 3000
app.use(morgan('tiny'))
app.use(express.json())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended: true}))
const catchTCP = async dataLine => {
dataLine = 'DATA,zoneA,20'
try {
if (dataLine.indexOf("DATA") >= 0) {
var stream = dataLine.split(",")
var streamData = {
zone: stream[1],
battery: stream[2]
}
console.log(streamData)
}
} catch(err) {
console.log("error:", err)
}
}
catchTCP()
app.listen(PORT, () => console.log(`App listening at http://localhost:${PORT}`))
I would like to replace the 'dataLine' object by an entry point for this TCP/IP data. What would be the best way to forward TCP/IP data to the HTTP server's port?
Both servers run on the same network, so I've been told socket.io would not be the best fit.
Replace the catchTCP function on your HTTP server with a middleware route:
app.post("/receive", express.text(), function(req, res) {
var dataLine = req.body;
/* Your code from catchTCP */
res.end(); /* finish the HTTP response */
});
Then your TCP/IP server can send an HTTP request with the following code:
var s = net.createConnection(PORT, "localhost", function() {
s.end(`POST /receive HTTP/1.1
Content-Type: text/plain
Content-Length: ${data.toString().length}
${data}`);
});
This is the TCP/IP-level representation of the HTTP request. But I would not do it that way, I would rather use a proper HTTP client. Which is not a problem if your TCP/IP server is programmed in Node.js anyway:
const http = require("http");
http.request("http://localhost:${PORT}/receive", {
method: "POST",
headers: {"Content-Type": "text/plain"}
}).end(data.toString());

req.body is empty when sending data in server, in local works

I'm trying to send data to index.js, in localhost it's works correctly but when I deploy to my server it's not working. I see problem seems similar :
here. but it's not work for me
client.js :
sending data to index.js /subscribeA
await fetch("https://example.com:30000/subscribeA", {
method: "post",
body: JSON.stringify({ dataSubscribe: subscription, dataNotif: dataNotif}),
headers: {
"Content-Type": "application/json"
},
mode : 'no-cors'
});
console.log("Push Sent...");
}
then in index.js :
var express = require('express');
const port = process.env.PORT || 30000;
const app = express();
const http = require('http');
const https = require('https');
const fs = require('fs');
var server = http.createServer(app);
const privateKey = fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem', 'utf8');
const certificate = fs.readFileSync('/etc/letsencrypt/live/example.com/cert.pem', 'utf8');
const credintials = { key: privateKey, cert: certificate };
server = https.createServer(credintials, app);
server.listen(port, () => console.log(`Server started on port ${port}`));
const io = require("socket.io")(server, {
// allowEIO3 = true,
cors: {
credentials:true,
origin: '*',
methods: ["GET", "POST"]
}
})
const webpush = require("web-push");
const bodyParser = require("body-parser");
const path = require("path");
// Set static path
app.use(express.static(path.join(__dirname)));
app.use(bodyParser.json());
const publicVapidKey =
"BJthRQ5maDga7OSXsPC1ftGw-n16F7zQBEN7EUD6XxcfTTvrLGWSIG7y_JxiWtVlCFua0S8MTB5rPziBqNx1qIo";
const privateVapidKey = "3KsvdasAdSoCdsd0dIG_o9B0Ozvl1XDwI63JRKNIWBM";
webpush.setVapidDetails(
"mailto:test#test.com",
publicVapidKey,
privateVapidKey
);
// Subscribe Route
app.post("/subscribeA", (req, res) => {
console.log(req.body);
// Get pushSubscription object
// console.log(req.body.dataSubscribe);
const subscription = req.body.dataSubscribe;
const dataNotif = req.body.dataNotif;
if(dataNotif == null){
console.log('kosong rek');
}else{
console.log(dataNotif);
}
// Send 201 - resource created
res.status(201).json({});
// Create payload
const payload = JSON.stringify({ head: "yobro", content: "kontennnya bro"});
// Pass object into sendNotification
webpush
.sendNotification(subscription, payload)
.catch(err => console.error(err));
});
io.on('connection', function (socket) {
socket.on('notifikasi', function (data) {
io.sockets.emit('notifikasi', {
isi_notif: data.isi_notif});
});
});
Request Payload
{dataSubscribe: {,…}, dataNotif: {head: "#username", content: "yo"}}
dataNotif: {head: "#username", content: "yo"}
dataSubscribe: {,…}
So, it's sending data correctly, but in index.js when I use console.log(req.body) it return empty array {}.
Using no-cors in your fetch() means that the content-type can only be one of the following: "application/x-www-form-urlencoded", "multipart/form-data", or "text/plain" (some more explanation here). So, your "application/json" is not allowed and thus the server doesn't properly read/parse the body.
Only simple headers are allowed with no-cors which you can read about here.
You will have to stop using no-cors with your fetch to use JSON or change the content to use one of the allowed content-types.
FYI, in cases like this, it's generally helpful to log out the important expected aspects of the incoming request. In this case, you could log the content-type and see what you're getting. You could also look at the request as it's being sent from the browser in the network tab of the Chrome debugger. Either would probably show you something related to the content-type.

sending and recieving a file in Nodejs with Express

I'm writing a server and a client with Node.js, the server uses express and the client uses axios.
I'm trying to send an image file from the client to the server. I found somewhere here this bit of code for the client:
let file = fs.createReadStream(file_path);
let form_data = new FormData();
form_data.append("picture", file);
let post_config = {
method: "post",
url: SERVER_PICTURE_URL,
headers: {"Content-Type": "multipart/form-data"},
data: form_data
}
axios(post_config).then(_ => {console.log("sent");} );
But I can't figure out what's supposed to be on the server side. I've tried the most obvious solution, writing response.data or response.form to a file, but both are undefined.
Is there some parser I'm supposed to use? And if so, how?
I'm not sure about the client that you wrote, but in express, you need to use express-fileupload package for getting the picture from req.files
const express = require('express');
const fileupload = require("express-fileupload");
const app = express();
const port = 3000;
app.use(fileupload());
app.post('/picture', (req, res) => {
const files=req.files;
res.send(files)
})
app.listen(port, () => {
console.log(`app listening at http://localhost:${port}`)
})

How to recieve a file using request.get()?

I am writing a server that is meant to serve and receive files. It is written in node.js, using express.js. I also have a client, also written in node, which is meant to send a request to the server and receive the files on the server.
Server-side
const express = require("express");
const app = express();
const file = "./samplefiles/Helloworld.txt";
app.get("/", (res)=>{
res.download(file);
});
module.exports = app; //this exports to server.js
const http = require("http");
const app = require("./app.js);
const port = 8080;
const server = http.createServer(app);
server.listen(port, () => {
console.clear();
console.log("server running");
})
Client-side
const request = require("request");
request.get("http://localhost:8080/", (req, body) => {
console.log(body);
console.log(res);
});
If I try to access it by my browser I am asked what I want to do with the file, it works. However, Is I run my client-side code it prints the body and the res(being null). I expected the file name and it's content to be in the body but only the content of the file was in the body.
I want to receive the whole file, is possible, or at least get the name of it so that I can "make" a copy of it on the client-side.
Change code your server side to:
const port = 8080;
const express = require("express");
const app = express();
const path = require('path');
app.get("/", function(req, res){
res.sendFile(path.join(__dirname, 'app.js'));
});
app.listen(port, () => {
console.clear();
console.log("server running");
});
Change code your client-side to:
var request = require('request');
request('http://localhost:8080/', function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print data of your file
});
You need to install request npm i request for client side
You can serve up any files you want with express static method:
app.use(express.static('public'))
in this case just put all the files you want to serve in folder called public and then you can access it by localhost:8080/Helloworld.txt.
I ended up working around it.
I sent the file name as a header and was thus able to create a replica of the file I wanted to download using the body info and the filenameheader.

Is there a way to stream download a mp3 file that is being converted on a nodejs server?

I am looking for a way to send the url to the nodejs server and respond the user with the mp3 file download.
I searched some examples, and read about requests and responses, but I am not sure what the problem really is.
This is the Javascript for the HTML:
var downloadBtn = document.querySelector('.download_button');
var URLinput = document.querySelector('#myUrl');
downloadBtn.addEventListener('click', () => {
console.log(`URL: ${URLinput.value}`);
sendURL(URLinput.value);
});
function sendURL(URL) {
window.location.href = `http://localhost:4000/download?URL=${URL}`;
}
This is the Javascript for the Nodejs server:
const express = require('express');
const cors = require('cors');
const ytdl = require('ytdl-core');
const app = express();
const ffmpeg = require('fluent-ffmpeg')
app.use(cors());
app.listen(4000, () => {
console.log('Server Works !!! At port 4000');
});
app.get('/download', (req,res) => {
var URL = req.query.URL;
res.header('Content-Disposition', 'attachment; filename="file.mp3"');
let stream = ytdl(URL, {
quality: 'highestaudio',
}); //HERE THE STREAM FILE IS SELECTED TO BE CONVERTED TO MP3
ffmpeg(stream)
.audioBitrate(128)
.pipe(res); // HERE IS CONVERTED AND WHERE I WANT IT TO SEND IT AS A DOWNLOAD TO THE USER.
});
I expected it to stream download the file but instead it gets me to the nodejs server page to /download/url_to_vid

Resources