app.delete("/tm/v1/tasks", (req,res) => {
Task.findOneAndDelete(req.body.id, (err, car) => {
if (err){
res.status(500).json({msg: error});
}
res.status(200).json({tasks});
})
});
The above isn't working and is giving an error 404. any ideas?
please check if you have are using correct url
we can add body to delete request in postman or curl but its not possible to pass body in javascript, dart (http package), etc.
you can rewrite function as
app.post('/tm/v1/delete-tasks', (req, res) => {
// write your code here...
});
Related
I have an express get route that downloads a CSV file in the browser. That part works fine, but now I want to delete the file using fs.unlink after it is downloaded because it is being stored on the host os in the temporary directory and they build up.
If I try to run the code snipped below, it cannot complete the download because it gets deleted by unlink before it can process (I think).
router.get('/downloadCsv', function(req, res, next) {
res.download(downloadCsvPath);//download file
fs.unlink(downloadCsvPath, (err) => {//delete file from server os
if (err) {
console.error(err);
} else {
console.log('removed: ' + downloadCsvPath);
}
});
});
It gives this error:
Error: ENOENT: no such file or directory, stat '/var/folders/fw/03jxpm311vs548bvf9g_1vxm0000gq/T/<filename>.csv'
As a workaround, I added a 3 second timeout to let the file download first, then delete:
router.get('/downloadCsv', function(req, res, next) {
res.download(downloadCsvPath);//download file
setTimeout(() => {
fs.unlink(downloadCsvPath, (err) => {
if (err) {
console.error(err);
} else {
console.log(downloadCsvPath);
}
});
}, 3000);
});
This works, I get the file downloaded and then it gets deleted from the temporary directory.
But, if connection was poor and it takes longer than 3 seconds, it would probably fail again. There has got to be a better way to run this fs.unlink block of code only once the res.download finishes. I am new to express js so I don't know how to do this. I want to do something like:
res.download(path).then(() => {
//do something
});
But it does not offer this.
I want to run a function after my expressjs res.download, but I do not know a way other than setTimeout
As per Express documentation, res.download() can accept a callback function, which is invoked when the transfer is complete or when an error occurs:
router.get('/downloadCsv', (req, res, next) => {
res.download(downloadCsvPath, (err) => {
if (err) {
// Handle error, but keep in mind the response may be partially-sent
// so check res.headersSent
} else {
fs.unlink(downloadCsvPath, (err) => {
if (err) {
console.error(err);
} else {
console.log(downloadCsvPath);
}
});
}
});
});
Here is the link to the relevant section in the Express documentation.
Hope this helps.
I'm having some trouble error handling my authentication API calls. When I send the 500 status from Express, my frontend (Vue in this case) only picks up the message Request failed with status code 500 rather than something more helpful for triage like this is the worst error ever (in the example below).
In the below example, when I call '/post' from the API, I throw an error which is handled by my custom middleware. The middleware successfully handles the error and sends the appropriate status to my frontend, but I can't figure out how to send useful messages (e.g. 'this is the worst error ever') / access them in the front end.
Is this a common use case? Am I doing anything obviously wrong? Does the message I send come up in the (err) parameter, or do I need to add a resp parameter?
Express Route for '/login'
router.post('/login', (req, res, next) => {
throw Error('this is the worst error ever')
})
Custom express error handler
app.use(function(err, req, res, next) {
res.status(err.status || 500).send({
error: {
status: err.status || 500,
message: err.message || 'Internal Server Error',
},
});
});
Handle the API Response in Vue
login (e) {
e.preventDefault();
UserService.login(this.username, this.password) //this is simple axios post call
.catch((err) => {
this.loginStatus = err.message
return
})
}
Found the answer to this for those that find this helpful. The err that is caught has a response variable. This is where the data is sent via the express send command. See corrected code below for the frontend:
login (e) {
e.preventDefault();
UserService.login(this.username, this.password) //this is simple axios post call
.catch((err) => {
this.loginStatus = err.response.data.message
return
})
}
I think you need to add:
Throw new Error()
instead of
Throw Error
If you are making an asynchronous calling you can do this
app.get('/', function (req, res, next) {
fs.readFile('/file-does-not-exist', function (err, data) {
if (err) {
next(err) // Pass errors to Express.
} else {
res.send(data)
}
})
})
Code should look like this:
router.post('/login', (req, res, next) => {
throw new Error('this is the worst error ever')
})
Check this in express documentation
I'm trying to get access to a pdf from a Google Drive. Whether this access is downloading or viewing, it doesn't really matter, it just needs to be available.
I am using Javascript and NodeJS, with express and google drive api.
I have the following function below which downloads a pdf. But silly me thought this was correct because it worked locally. Then when I deployed it I realised the target filepath no longer makes sense.
function downloadDoc (sourceID, targetName, callback) {
const dest = fs.createWriteStream(`${os.homedir()}/downloads/`+targetName);
drive.files.get(
{sourceID, alt: 'media'},
{responseType: 'stream'},
(err, res) => {
if (err) {
console.error(err);
}
res.data.on('end', () => {
console.log('Done downloading file.');
callback();
})
.on('error', err => {
console.error('Error downloading file.');
throw err;
})
.pipe(dest);
});
}
So what I need to do, is take the data (or response?) from this function and send it over to client side. I assume this is simple to do but, being a simple man, I find myself stuck. I have written this, with the intention that a user can click a link on client side, requesting this URL and calling the function to download the pdf.
app.get('/download_pdf', (req, res) => {
downloadDoc(documentID, 'docName.pdf', ()=>{
console.log("downloaded pdf");
});
res.end();
});
I'm thinking I need to change the argument provided to pipe() since obviously I can't use the filepath.
Similar questions I've checked:
Display Pdf in browser using express js
How to send a pdf file from Node/Express app to the browser
Send pdf via express to js client and download
While these questions are very related to this, I think my issue is due to a lack of understanding of callbacks or requests/responses. I want to learn this properly - not just ask for answers - but as it is, I'm becoming very pressed for time and need a solution soon.
You should be able to simply pipe the returned readable stream to the express res object (which is a writeable stream):
app.get('/download_pdf', (req, res) => {
drive.files.get({
fileId: "your-file-id-here",
alt: 'media'
})
.on('end', function () {
console.log('Done');
})
.on('error', function (err) {
console.log('Error during download', err);
})
.pipe(res);
});
Edit:
as mentioned here, drive.files.get does return a promise. So you need to change it to:
app.get('/download_pdf', (req, res) => {
drive.files.get({
fileId,
alt: 'media'
}, {
responseType: 'stream'
}).then(response => {
response.data
.on('end', function () {
console.log('Done');
})
.on('error', function (err) {
console.log('Error during download', err);
})
.pipe(res);
});
});
So I figured out a way. I'm not sure if this is bad practice but it seems to work. I distinguished between the two response objects by referring to one as response and one as res.
app.get('/download_pdf', (req, res) => {
const docId = req.query.id;
drive.files.get({
fileId: docId,
alt: 'media'
}, {
responseType: 'stream'
}).then(response => {
response.data
.on('end', function () {
console.log('Done');
})
.on('error', function (err) {
console.log('Error during download', err);
})
.pipe(res);
});
});
Posting this in the event that somebody else has a similar issue.
Where should i put async and await?
result is
work2
work1
app.post('/upload', (req, res) => {
const txtupload = multer().any()
let validate = true
txtupload(req,res, (err)=>{
console.log('work1')
validate = false
})
if(validate){
console.log('work2')
//code
}
});
The upload function from multer doesn't return a promise, so async/await isn't applicable. Instead, issue your response in the callback.
Your real question seems to be: How do I use multer to handle file uploads? For that we go to the multer documentation. Adapting that documentation to your code:
app.post('/upload', (req, res) => {
const txtupload = multer().any();
txtupload(req,res, (err) => {
if (err) {
// ...it failed, send a failure response via `res`...
} else {
// ...it worked, send a success response via `res`...
}
});
// Don't do anything here, the upload hasn't been processed yet
});
But refer to the examples in the documentation, there are other patterns for using multer.
Since it's an arrow function, you have to put it before the parameters:
app.post('/upload', async (req, res) => { ... }
Using ReactJS, Redux, Webpack, Node.js and Express with MongoDB, I am following the tutorial https://github.com/vasansr/mern-es6 and trying to integrate it into my project. First, I am trying to make a POST request to the server I created. And it gets a response with a success and no error is logged. Yet inside the server POST API, it does not log console.log('Req body', req.body);, and in terminal I checked to see if the database has been created with mongo -> show dbs but it is empty.
Could it be that something is intercepting the request from the server? What could be the issue?
This...
app.use('/', function (req, res) {
res.sendFile(path.resolve('client/index.html'));
});
comes before:
app.post('/api/users/', function(req, res) {
//...
});
Since it's app.use the POST /api/users will still hit that middleware, and res.sendFile ends the request/response. You'll probably see that your post is getting back the client HTML.
Try moving your client HTML endpoint to the end of your middleware, just before the error handlers if you have them. That way, it'll only get used if none of your API endpoints match. Or if you want just GET / to return the HTML, change use to get:
app.use(webpackDevMiddleware(compiler, {noInfo: true, publicPath: config.output.publicPath}));
app.use(webpackHotMiddleware(compiler));
app.use(express.static('dist')); //where bundle.js is
app.use(bodyParser.json());
app.post('/api/users/', function(req, res) {
console.log('Req body', req.body);
var newUser = req.body;
db.collection('users').insertOne(newUser, function(err, result) {
if(err) console.log(err);
var newId = result.insertedId;
db.collection('users').find({_id: newId}).next(function(err, doc) {
if(err) console.log(err);
res.json(doc);
});
});
});
app.get('/', function (req, res) {
res.sendFile(path.resolve('client/index.html'));
});
app.post('/api/users/', function(req, res) {
console.log('Req body', req.body);
var newUser = req.body;
db.collection('users').insertOne(newUser, function(err, result) {
if(err) console.log(err);
var newId = result.insertedId;
db.collection('users').find({_id: newId}).next(function(err, doc) {
if(err) console.log(err);
res.json(doc);
});
});
});
I have a small comments about this code, for if(err) console.log(err); i think you should change to if(err) return console.log(err);.
For error case, i think you need return, otherwise the below part will be excuted, and there will report some error.