node.jsexpressbody-parsernode-pdfkit

How to pass req.body from router file to module?


I'm trying to separate my code into modules so the main files (app and router) stay relatively neat. The webpage accepts a POST from form and returns the user a PDF generated with user input.

In router.js I want to separate what's in the {} of the if blocks into separate files (in the first block I commented it out). However, when I do that, the separate file doesn't receieve the body info from the middle-ware (I get ReferenceError: req is not defined).

How can I export the {} of the if blocks (which will get very verbose, and there will be many more if blocks, which is why example1.js is in a folder pdfGenerators) into separate files so router.js stays clean?

index.html

<!doctype html>
<form method="post" action="sendPDF">
  <input name="userInput" type="text">
  <button type="submit" name="submit" value="example1">Send Example 1</button>
</form>
<form method="post" action="sendPDF">
  <input name="userInput" type="text">
  <button type="submit" name="submit" value="example2">Send Example 2</button>
</form>

app.js

const express = require('express');
const app = express();
const path = require("path");    
app.use(express.urlencoded({ extended: false }));

//server started?
var port = process.env.PORT || 3000;
app.listen(port,() => {
    console.log('Started on PORT 3000');
  })
//For local testing only, using nginx normally
app.use(express.static(path.join(__dirname, "public"), {
    extensions: ['html']
}))

//sendPDF routing
require('./router')(app);

router.js

const PDFDocument = require('pdfkit');

module.exports = function(router) {
    router.post('/sendPDF', (req, res) => {

        if (req.body.submit =='example1') {
            require('./pdfGenerators/example1')();
            /*const doc = new PDFDocument();

            doc.text(req.body.userInput);

            // Pipe its output as http response
            res.statusCode = 200;
            res.setHeader('Content-type', 'application/pdf');
            res.setHeader('Content-disposition', 'attachment; filename=Example 1.pdf');
            doc.pipe(res);
            doc.end();*/
        }

        if (req.body.submit =='example2') {
            const doc = new PDFDocument();

            doc.text(req.body.userInput);

            // Pipe its output as http response
            res.statusCode = 200;
            res.setHeader('Content-type', 'application/pdf');
            res.setHeader('Content-disposition', 'attachment; filename=Example 2.pdf');
            doc.pipe(res);
            doc.end();
        }
    })
};

example1.js

const PDFDocument = require('pdfkit');
module.exports = function () {
const doc = new PDFDocument();

doc.text(req.body.userInput);

// Pipe its output as http response
res.statusCode = 200;
res.setHeader('Content-type', 'application/pdf');
res.setHeader('Content-disposition', 'attachment; filename=Example 1.pdf');
doc.pipe(res);
doc.end();

};

By the way, am I thinking in the right direction or do I have my architecture logic messed up, and is this an efficient way to generate such pdfs with pdfkit or will it cause problems with multiple simultaneous users?


Solution

  • You can use function arguments as a way to expose req and res objects to example1 module.

    In your router,

    const PDFGenerator = require('./pdfGenerators/example1');
    module.exports = function(router) {
        router.post('/sendPDF', (req, res) => {
    
            if (req.body.submit =='example1') {
                PDFGenerator(req, res);
            }
            // ...
    }
    

    And then in your PDFGeneraor example1 module, you need to accept these parameters.

    module.exports = function (req, res) {
        //...
    }