javascripthtmlnode.jsexpressvariables

Passing Node.js varaibles from back-edn to front-end using express


I would like to pass the IP variable obtained from request.headers['x-forwarded-for'] in my server.js file to my webpage index.html and displaying it. I have tried passing it in the <script> tag and even within the tag to display it immediately. That is my script now:

server.js:

    const express = require('express')
    const server = express()
    const engine = require('consolidate');
        server.engine('html', engine.mustache);
        server.use(express.static('./'));
            server.get("/", function (request, response) {
    clientIP = request.headers['x-forwarded-for']
    response.render(__dirname + "/index.html", {
        ip: clientIP
    })
})

index.html:

<body>
    <h1>Wolfram Bot</h1>

    <form method='GET' action="/eval">
        <div class="container">
            <div class="prompt left-pane">
                <span>Enter a command to evaluate:</span>
            </div>

            <br> <br>

            <div class="right-pane">
                <input type="text" name="input" placeholder="" />
                <input type="text" name="code" placeholder="code" />
            </div>
        </div>

        <br>

        <div class="submit-cmd">
            <input type="submit" value="Send Command" />
        </div>

        <div>
            <span>IP: <a id="ip"></a></span>
        </div>

    </form>
</body>

<script>
    var ip = "<%= name %>"
    console.log(ip)
    document.getElementById('ip').innerHTML = ip
</script>

Thanking in advance!


Solution

  • If you are using Moustache as a template engine (with Consolidate), please check its documentation about how the templating works: https://www.npmjs.com/package/mustache

    I think what you need there is to use {{ ip }} in the script like:

    <script>
        var ip = "{{ ip }}"
        console.log(ip)
        document.getElementById('ip').innerHTML = ip
    </script>
    

    Actually, you may want to set the ip right into the html, getting rid of the <script> stuff:

    <span>Your IP is begin logged: {{ ip }}</span>
    

    Update

    I've run locally an example to understand why is not working, and here are my findings:

    server.js

    const express = require('express')
    const server = express()
    const engine = require('consolidate');
    const port = 3000;
    
    server.engine('html', engine.mustache);
    // set .html as the default extension
    server.set('view engine', 'html');
    server.set('views', __dirname + '/public');
    
    server.get('/', (req, res) => {
        const acceptHeader = req.get(`Accept`)
        console.log(`Accepting: ${acceptHeader}`);
        
        res.render(`server`, {
            ip: acceptHeader
        })
    })
    
    server.listen(port, () => {
        console.log(`running on port ${port}`);
    });
    

    I had to set view engine and views to make it work. Also I had to install mustache, even thou it is not directly used by my code (the docs state that this is a required step).

    Now, there is something interesting here: the html file is called index.html, and it was loaded by express as the default html when / was called, without running my listener at /.
    This usually happens when the root path is called (/), the server tries to load what is in index.html by default, as a static content, and we may not notice the listeners we setup are not being used.
    I discovered it when I changed the name of the file to server.html.

    Now this file, is rendering the dynamic content without javascript, check it out:

    server.html

    <html lang="en">
        <head>
    
        </head>
        <body>
            <h1>Wolfram Bot</h1>
    
            <form method='GET' action="/eval">
                <div class="container">
                    <div class="prompt left-pane">
                        <span>Enter a command to evaluate:</span>
                    </div>
    
                    <br> <br>
    
                    <div class="right-pane">
                        <input type="text" name="input" placeholder="" />
                        <input type="text" name="code" placeholder="code" />
                    </div>
                </div>
    
                <br>
    
                <div class="submit-cmd">
                    <input type="submit" value="Send Command" />
                </div>
    
                <div>
                    <span>Accept Headers: {{ ip }}</span>
                </div>
    
            </form>
        </body>
    </html>
    

    Also, I'm not displaying the IP because it's not always in the request, so I've modified it a bit to display the Accept header, but the logic is the same.