I am fairly new to Node-Express. I am using the Express Router for routing the request. What I am basically doing is a video view, then delete function.
This is my code.
router.get('/videodelete', function(req, res) {
// Some synchronous operation using sync-exec
res.writeHead(200, {
"Content-Type": "text/html"
});
res.end('<video src="../video/video.mp4" controls></video>');
// response is sent. Now delete the file after the response is shown.
fs.unlink("../video/video.mp4");
})
I also tried fs.unlinkSync. In all these cases, the delete operation is happening before sending the response. I wish to trigger the delete operation only after sending response. Is there any way to perform this action only after sending the response?
Related
Trying to keep my code organized. I have a controller directory and router directory. The goal is to make an api call and retrieve data.
CONTROLLER
function searchName(req, res) {
res.setHeader("user-key", process.env.APIKEY)
res.redirect(`https://api-endpoint.igdb.com/games/?search=${req.params.game}&fields=*`)
}
ROUTER
router.get('/search/:game', Controller.searchName)
I export router, and require it in my server.js file. In POSTMAN, this works fine; I do have my API Key hard coded in Postman. I've tried many different methods but can't seem to pass the header with my ApiKey when making the initial request in the code. Additionally, being new to nodejs, I'm not sure if the request redirect is sufficient in this scenario. Ultimately, setHeader is not working
It sounds like you're trying to make an async call to another service, pull back some data, and send that back to the client that called your service. In a nodejs application it's quite trivial to make a new HTTP request. Nodejs has a built in HTTP.Agent, but I'd suggest trying out the axios library as it makes it even easily. This will result in something like this:
const axios = require('axios');
function searchGame(req, res) {
const requestOptions = {
method: 'GET',
uri: `https://api-endpoint.igdb.com/games/?search=${req.params.game}&fields=*`,
headers: {
"user-key": process.env.API_KEY
}
}
axios.get(requestOptions)
.then(function (response) {
// This is the data the remote service gave back
res.send(response.data);
})
.catch(function (error) {
// The remote gave an error, lets just forward that for now
res.send({error: error});
});
}
Here we build an axios request from the req object, we make the request using axios.get, we then wait for the "promise" (this is an async javascript concept if you've not come across it before), then we take the response from that and forward it back as the res. Lets pretend for argument sake that this is a JSON response, but it could be anything.
I've been researching this issue for several hours now and found something odd. Using ExpressJS, Firebase, and React for a small app, and need to call the Firebase Database via the Express Backend, and I also need to make post requests to store data in the database via the Express Backend.
Functionality: I make a post request to the backend to add data to the database. Since Firebase is real time db, the data will immediately reflect on the page.
Problem: The issue is, when I make a post call to the backend and that completes, the page refreshes but the data doesn't show because of this
ERROR: [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
/**
* Add new note to Firebase
* Real-Time Database
*/
app.post('/addNote', (req, res)=> {
var title = req.body.note.title;
var body = req.body.note.body;
var userId= req.body.note.uid;
db.notes.push({
title: title,
body: body,
uid: userId
})
res.send("Success")
})
app.get('/all', (req, res, next)=> {
db.notes.on('value', snapshot => {
return res.send(snapshot.val());
})
})
Possible Solution: I've found that using the code below, I can make a post request, manually refresh the page, and the data will reflect with no header error. I'm trying to code the proper functionality but can't seem to figure out where the code is sending multiple responses with the db.notes.on because I'm only sending res.send one time. The clear difference is (.on listens and updates immediately, while .once requires manual refresh)
/**
* Add new note to Firebase
* Real-Time Database
*/
app.post('/addNote', (req, res)=> {
var title = req.body.note.title;
var body = req.body.note.body;
var userId= req.body.note.uid;
db.notes.push({
title: title,
body: body,
uid: userId
})
res.send("Success")
})
app.get('/all', (req, res, next)=> {
db.notes.once('value', snapshot => {
return res.send(snapshot.val());
})
})
An on("value" listener to Firebase will fire:
straight away with the current value of the data,
and will then later also fire when the data changes.
Since you're sending the data in the response to the client in #1, the response will be closed/finished by the time #2 happens.
By using a once("value" listener this problem doesn't happen, since once() removes the listener after #1.
I am trying to make a slack app and to complete Oauth2, I have to send the URI below and get a JSON response back in the body.
The problem is, every time I am trying to use the function request() in my app.get() function, ejs is always trying to go and get my views. Now I tried rendering my specific view for app.get() but then when I use request() again, ejs is again trying to get a view.
How can I redirect to another url from my app.get and receive the JSON. I can use req.redirect() but I don't know how to get the response back.
Please please help! Thanks
app.get('/', (req, res) =>{
var options = {
uri: 'https://slack.com/api/oauth.access code='+req.query.code+'&client_id='+client_id+'&client_secret='+client_secret,
method: 'GET'
}
request(options, (error, response, body) => {
var JSONresponse = JSON.parse(body)
if (!JSONresponse.ok){
console.log(JSONresponse)
res.send("Error encountered: \n"+JSON.stringify(JSONresponse)).status(200).end()
}else{
console.log(JSONresponse)
res.send("Success!")
}
})
})
I have some files stored on a CDN server which is not to be directly accessed from client. So I proxy the requests via the public accessible server running ExpressJS and use request module to fetch the data server-side and return it in response.
It is working and in code looks something like this:
var request = require('request');
var app = express();
var internalUrl = 'https://my.storage-cdn.com/private/info/file.xml';
app.get('/somefile.xml', function (req, res) {
request(internalUrl).pipe(res);
});
The issues I faced with above method are:
the storage/cdn server appends some response headers of its own
which include some private information and as such can be a security
issue when exposed in response. And above method of piping the res
object to request doesn't remove those headers. It passes those
headers as is to response. I want to remove those headers.
I want to add some eTag and cache-control headers so the file could get cached
properly.
I have tried changing it to something like this:
app.get('/somefile.xml', function (req, res) {
request(internalUrl, function (err, response, body) {
if (!err && response.statusCode == 200) {
res.writeHead(200, {...}); // write custom headers I need
res.end(body);
}
});
});
This allows me to overwrite the headers to my liking, but in this method I have to wait for whole file to get downloaded on the server side first before I start sending the bytes in my response and with some files being as large as 1MB, it really affects the response time adversely.
So my question is - is there a way to not have to wait for whole file to download on server side before start sending response but still be able to manipulate response headers?
You can hook onto the 'response' event:
const SECRET_HEADERS = ['Set-Cookie', 'X-Special-Token']
app.get('/somefile.xml', function (req, res) {
request(internalUrl).on('response', function (response) {
SECRET_HEADERS.forEach(function (header) {
response.removeHeader(header)
})
}).pipe(res)
})
I am using AngularJs with NodeJs.
I have a scenario when upon a successful HTTP POST request, I need to redirect the user.
In the client through AngularJS, I make a HTTP POST request to a route:
$http.post('/aPath', data)
.success(function (result) {
//Handle success
})
.error(function (err) {
//Handle error
});
This route is handled within NodeJs that then does the actual POST. Upon success, within the route handler, I redirect:
function handlePostRequest (req, res) {
//Route handler
//HTTP POST Request
//Following code called when POST request is successful
if (result) {
//Successful post
res.redirect("http://www.google.com");
}
}
However, the browser does not navigate to google. Instead, in the error handler of the POST request within the AngularJS client, the control is reached.
I checked the server and find that the POST request is returned as status code 302 and thus is picked by the error handler for the POST request in the client.
I cannot figure out why, when the server successfully executes the redirect code, the control still reaches the client and that too the error handler. How do I redirect successfully?
Is it a HTTP POST in angular or an XHR? If it's an XHR you can't redirect the client from serverside, you'd need to send back an error which you then handle in your clientside script such as:
$http({
method: 'POST',
url: 'yoururl',
}).success(function(data, status, headers, config) {
// success stuff
}).error(function(data, status, headers, config) {
if (status == 302) {
window.location = headers('Location');
}
})
Successful XHRs come back with a status of 200. Your server handing back a 302 is technically correct, but it isn't what $http in Angular is expecting. If your server can hand you a 200, you can then do your redirect in the .success function of the $http request.