NodeJS API response fails after fs.writefile - javascript

I've created an API which I want to create a file, and after the file was written, request a log API and after its response, response relatively to the user.
I've simplified the code like this:
const express = require('express');
const router = express.Router();
const fetch = require("node-fetch");
const util = require('util');
const fs = require("fs-extra")
router.get('/works/', (req, res) => {
logData(res)
})
router.get('/fails/', (req, res) => {
let t = Date.now();
const writeFile = util.promisify(fs.writeFile)
writeFile(`./data/${t}.json`, 'test').then(function(){
logData(res)
})
})
function logData(res) {
return new Promise(resolve => {
fetch('https://webhook.site/44dad1a5-47f6-467b-9088-346e7222d7be')
.then(response => response.text())
.then(x => res.send('x'));
});
}
module.exports = router
The /works/ API works fine,
but the /fails/ API fails with Error: read ECONNRESET

OP clarified in the comments that he uses nodemon to run this code.
The problem is that nodemon watches .json files too and restarts the server. So the request that changes a JSON file fails with Error: read ECONNRESET.
To prevent nodemon from restarting server when you change .json files see this.
For example, you can add nodemon.json configuration file to ignore ./data directory (make sure to restart nodemon after this file is added):
{
"ignore": ["./data"]
}

Related

Read data from url in javascript

i'm trying to read data stored in google drive, on drive or other cloud storage using javascript
`
let btn = document.getElementById('action-btn');
btn.addEventListener('click', () => {
// let baseurl = document.getElementById('inputurl').value;
// let guidDcoument = baseurl.split('#guid=')[1];
// const query = encodeURIComponent('Select *')
// fetch('', {
// mode: "no-cors",
// method: "get",
// }).then(Response => console.log(Response))
fetch('https://docs.google.com/spreadsheets/d/1kwfv6L2lBrPw8OjHGyhO7YHOXFNwHYyPI_noM5TUMLw/edit?pli=1#gid=1097732605',{
mode:"no-cors"
})
.then((response) => { console.log(Response.error); })
.catch(console.error())
})
`
What I need is that given a url, I can read the data from the file, and then show them on my website.
I think that when I try to access any other cloud storage I will have the same problem. That it will be necessary to access the account to be able to read the data that would be a csv document.
First of all, what you're trying to achieve is called 'web scraping' and you can't use fetch for that, instead you should use puppeteer (in the server side), which is the most popular library for web scraping.
Run npm init -y to initialize a npm project and install puppeteer npm i puppeteer and also install express and cors npm i express cors in order to create a server that scraps data and sets it back to your client. So, instead of trying to scrap the information directly from the client you do it from the server with puppeteer.
Try the following .js server code:
const express = require('express')
const cors = require('cors')
const puppeteer = require('puppeteer')
const app = express()
app.use(express.json())
app.use(cors())
;(async () => {
const browser = await puppeteer.launch({headless: false})
const page = await browser.newPage()
app.use('/', async (req, res) => {
await page.goto('url-to-the-website')
const data = {}
return res.json(data)
})
})()
app.listen(3000)
And learn more about puppeteer: https://pptr.dev/.
And your client code should connect to this server to send scrape requests to it like this:
(async () => {
const res = await fetch('http://localhost:3000')
const rawjson = await res.json()
const json = JSON.parse(rawjson)
console.log(json)
})
Note: we wrap the code in anonymous functions with the reserved word async in order to use async and await syntax. More information: https://javascript.info/async-await.

TypeError: server.listen is not a function in NodeJS

When i create new folder i can able to see server.listen method but i can't see this method in my another folder which i use for NODEJS codes. I use Visual Studio Code and I can't understand why.
const http = require('http');
const server = http.createServer = ((req, res) => {
console.log(req);
});
server.listen(3000);
http.createServer is a function which takes the handler function as an argument, so you call it like this:
const server = http.createServer((req, res) => {
console.log(req);
});
In the code you posted, http.createServer = ((req, res) => {... attempts to assign the function to http.createServer.
Module http included in node. Try install #types/node. It works on me.
const http = require('http')
const server = http.createServer(() => {
console.log('got')
})
server.listen(3000)
Also, req and res should had type notation except any.

How to import object to another file?

I'm using Node.js to build a web application.
I have two files. Server.js - where I call the server to go online etc. And the other one is a file which includes a big object with data. I imported the file with data into server.js, I get the object in postman when I set the website to be live. But I can't dive inside the object to get the data inside the object. The error I'm getting says that the variable where my data is stored is not defined.
I think the fix is to import albumsData variable into server.js, but im completely stuck and can't find how to do it. If anyone has any idea, please share.
albumsData.js
const express = require('express');
const router = express.Router();
let albumsData = {
filled with data
}
router.get('/albumData', (req, res) => {
res.send(albumsData);
});
module.exports = router;
Server.js
app.use(require('./api/albumData/unikkatilData'))
app.use((req, res) => {
res.status(404)
.send(albumsData)
});
app.listen(4000, () => {
console.log('hello worldd')
})
If you want the albumsData object then you can do it like this:
In you albumsData.js file:
const albumsData = {
// Bunch of data
}
module.exports = albumsData
Then in your server.js file:
const albumData = require('./api/albumsData') // Make sure this path points directly to the albumsData.js file
move enter code here to new file (ex utils.js)
and export it exports.albumsData = albumsData; then you can call it
with const utils = require('./utils') ; utils.albumsData

can not get response return from node api into angular

I wrote a file upload snippet with multer in nodejs. It is working and files have been successfully uploaded to the server and I got the response(tested using postman),But when I call that API from client side(angular),I'm NOT getting the returned response from node.but file was uploaded. I'm using promise to handle responses.
const express = require('express');
const router = express.Router();
const upload = require('../startup/config');
router.post('/', upload.single('invoice'), (req, res) => {
return res.status(201).send({ status: 'success'});
});
module.exports = router;
client side
async onUpload() {
const uploadData = new FormData();
uploadData.append('invoice', this.selectedInvoice, this.selectedInvoice.name);
const result = await this.orderService.uploadInvoice(uploadData);
console.log('result', result); // <= not execute this line
}
order service
uploadInvoice(formData) {
return this.http.post('/api/invoices', formData).toPromise();
}
I need to run the line mentioned here, Did i miss something here? Need your help.
Thanks!

transfer files between two node.js servers over http

I have two node.js/express servers that communicate with each other with http. server A is also communicates with the browser and can handle file upload requests. When file is uploaded to server A i want to transfer it as is to server B for further processing. what is the best way to do so? preferably with request-promise module which is what i'm using for communication between the two servers.
This is what i got so far, but i am unable to transfer the file between the servers, the file is uploaded successfully to server A, and there is no Error while sending it to server B, but server B is doesn't recognise the request as file. what am i missing here?
Server A Routes:
'use strict';
// Routes
const express = require('express');
const router = express.Router();
const multer = require('multer');
const upload = multer();
const uploadController = require('./controllers/file/upload');
router.post('/upload',upload.single('file'),uploadController);
module.exports = router;
Server A uploadController:
'use strict';
const RP = require('request-promise');
module.exports = (req, res) => {
const body = req.body;
if(req.file) {
const file = req.file;
RP('http://serverB.net/process', {
method: 'POST',
formData: {file_buffer: file.buffer},
body: body
})
.then((response) => {
return res.status(200).send(response);
})
.catch((e) => {
return res.status(500).send(e.message);
})
}
else {
return res.status(500).send('unable to upload file');
}
};
Server B Routes:
'use strict';
// Routes
const express = require('express');
const router = express.Router();
const multer = require('multer');
const process = multer();
const processFile = require('./controllers/file/processFile');
router.post('/process', process.single('file'), processFile);
module.exports = router;
Server B processFile:
here i want to process the file from Server A but req.file is undefined
'use strict';
module.exports = (req, res) => {
if(req.file) {
// here i want to do something with the file.
}
};
router.post('/process', process.single('file'), processFile);
This line, specifically process.single('file') tells multer to look for a field file which will contain the actual file data. However, in your request you never specify a value for file. Change the name file_buffer to just file in your request. Or change your process.single() to process.single('file_buffer')
RP('http://serverB.net/process', {
method: 'POST',
formData: {
file: file.buffer,
body: body
}
})
.then((response) => {
return res.status(200).send(response);
})
.catch((e) => {
return res.status(500).send(e.message);
})
Now on Server B, inside processFile you should see a req.body with a field body that contains your entire body passed in your request and you should have a req.file now that contains your multer file object.
The encoding that you are using so send the file may not be multipart/form-data. Try setting that header in your file send request. Express req.files will only be populated with a multipart/form-data Express req.files will only be populated with a multipart/form-data . You're already using multer so I'm guessing the sending encoding is not quite right.
RP({
method: "POST",
uri: "serverB.net",
form: {
file: file.buffer
},
headers: {
"Content-Type": "multipart/form-data"
}
});

Categories