POST Request creates file, followed by GET Request to download - node.js

Trying to do something seemingly basic.
I'd like to create a POST request through which I'll be sending JSONs. These JSONs will be created into files, which I'd like to return to the user via download.
The use case for this is that I'm building an application which takes a form and converts it into a JSON for upload to a MongoDB database. Users can load these JSONs into the application to re-load their old records as templates.
This is how I'm approaching it as of now:
// Download JSON Previews
var jsondownload = {};
// Grabs the JSON from POST request
app.post('/api/download', function(req, res, next){
jsondownload = {};
var json = req.body;
jsondownload = json;
res.json(jsondownload);
next();
});
// Immediately downloads the JSON thereafter
app.get('/api/download', function(req, res){
res.set({"Content-Disposition":"attachment; filename='test.json'"});
res.send(jsondownload);
});
What's the right way to do this?

There is no one "right" way to do it, but a few solutions include:
Remove the GET route handler (and the jsondownload variable) completely and just respond immediately with the Content-Disposition set appropriately. This is the better of the 3 because it reduces code and keeps things simple.
Use a simple redirect in your POST route handler. Instead of responding with the JSON immediately, you would do res.redirect('/api/download').
Do more or less what currently doing, but move the logic (the res.set() and res.send()) to a separate function that gets called from both route handlers.

Related

use req.body data from the api route handler in a external javascript file in nextjs api

I need to send the req.body (data received from the client to API route via post request) data from the API route to a separate javascript file in the backend api.
const payload = {}
const handler = async (req, res) => {
payload = req.body
res.status(200).json({ status: 'success' })
}
export default handler
I declared a variable outside the route handler function and assigned req.body to it, but then I realized that I can't use this global variable inside the handler function. I don't know the reason. Is there any specific way of achieving what I'm trying to achieve here?
I request to please elaborate the use case a bit more. Based on current requirements.
I can understand that-
You need to send the req.body to another JavaScript file. Now here can be 2 cases.
You need to store req.body in a file, and use it for later processing.
Pass the req.body to another function which is present in another JavaScript file.
In this case, you can export the function from another file and import in this main file and call the function in your controller and pass req.body as Payload.
I think your use case will be second one, if not please update question and I will be happy to help you out.

How to push a sequence of html pages after one request using NodeJS and ExpressJS

I am turning around in stackoverflow without finding an answer to my question. I have used expressJS fur several days in order to make an access webpage that returns first an interstitial and then a webpage depending on several informations I can get from the requester IP and so on.
My first idea for the interstitial was to use this piece of code:
var interstitial = function(req, res, next) {
res.render('interstitial');
next();
}
router.get('/', interstitial, nextPage);
setting a timeout on the next nextPage callback function of router.get().
However it looks that I could not do that. I had an error "Error: Can't set headers after they are sent.". I suppose this is due to the fact that res.render already give a response to the request and in the philosophy of express, the next function is passing the req, res args for another reply to another function that possibly could do it. Am I right?
In that case, is there a way to give several answer, with timeout to one request? (a res.render, and after that in the next callback a rest.send...).
Or is this mandatory to force client to ask a request to give back another response? (using js on the client side for instance, or timers on client side, or maybe discussing with client script using socket.io).
Thanks
Not sure I fully understand, but you should be placing all your deterministic logic within the function of the handler you're using for your endpoint.
Kinda like so:
router.get('/', function(req, res){
var origin = request.origin;
if (origin == '11.22.33.44'){
res.send('Interstitial Page.');
}else{
res.send('Home Page');
}
});
You would replace the simple text responses with your actual pages, but the general idea is that once that endpoint is handled you can't next() it to secondary handler.

With Node.js, how can I make two HTTP GET requests and combine the resulting data and send it back to a user?

Say I have the following code that sends back json data (that I get from example.com first) back to a user that made a post request
app.post('/riot', function(request, response) {
var riotAPI = https.get("https://example.com", function(riotResponse){
var body = "";
riotResponse.on('data', function(chunk){
body+= chunk;
});
riotResponse.on('end', function(){
response.type('json');
response.end(body);
});
});
});
What do I do if I want to get more data from a different website and send json data from both website back to user? I am using express.
There are a number of ways you can do this. I would suggest using the request npm module instead of calling https directly. With request you can simply pass in callback which is called when a request finishes, so no need to deal with chunks of data.
If you take this approach then you can just use something like async.parallel() to run both requests in parallel. async.parallel takes one callback that is called when all of its async functions have finished.. and that is where you would send your response.

Where does the /api directory come from in an Express application?

For example:
router.get('/api/todos', function (req, res){
db.todos.find(function (err, data){
res.json(data);
});
});
I am having a hard time understanding what '/api/todos/ actually means. I don't have a directory name either one of these in my application. What exactly is this and where is it?
/api/todos/ does not refer to a local file, it corresponds to a URL request. In the function you provided, if you were to add this route to an express app then visit http://localhost/api/todos, the server would respond with the JSON data returned from the database query you are making.
router.get('/api/todos', function (req, res){
This first line accepts all GET requests to /api/todos, and passes the req and res objects into a callback for you to work with. See http://www.murvinlai.com/req-and-res-in-nodejs.html for an explanation of those objects.
db.todos.find(function (err, data){
Here, it is assumed that you have a db object which may perform database lookups based on some kind of input parameters.
res.json(data);
The res.json method simply sends the JSON back to the client that requested it.
See https://www.packtpub.com/books/content/understanding-express-routes for further info on routing in express.
That's not a directory. That's a URL. Routers route URLs to resources. It could be files, it could be other URLs or most commonly it could be some javascript logic that generates the response you want (JSON, XML, HTML, PDF etc.)

Is there a way to accept multipart forms on meteorjs? i.e. image uploads?

I want to be able to add image uploads to a site I'm working on, but I don't know how that is supposed to work with meteorjs. Is there a way to accept multipart forms on meteorjs? i.e. image uploads?
I could always rackup a small sinatra app for file uploads but I'd rather not.
You need to write a middleware to accept such requests.
WebApp.connectHandlers.stack.splice(0, 0, {
route: '/your/url/for/inputs',
handle: function(req, res, next) {
// Handle request and response
// just like you would do in node.js.
// Make sure to wrap your db calls in Fibers.
// Use next() if you change your mind
// and don't want to handle this request after all.
},
});
Looks like eventminded has a file upload package you could use.
https://www.eventedmind.com/posts/meteor-build-a-file-upload-package

Resources