Passing Variable from Node.js Server to Client - node.js

On my node.js server I have the following code:
//Generate a token
var token = capability.generateToken();
//Serve the page
var html = fs.readFileSync('learn.htm').toString();
response.writeHead(200, {"Content-Type": "text/html"});
response.end(html);
}
Now on the client side (in learn.htm) I want to access the token variable. My question is, how do I pass the variable to the client in the response? There must be a simple way of doing this but I'm struggling to wrap my head around it.

You should look into using a template language for your HTML. There are several available, just search for node.js template language or using npm:
npm search templates
Edit: Some popular ones are jade, ejs, hogan.js.

You could send some JavaScript to the client which sets the variable. Or you could store it in a data- attribute e.g. of the body tag (<body data-token="...">) and then access it via $('body').data('token') in case you have jQuery on the client side.
If you need it for a form you can also store it in a hidden input field.

Put something like:
<input type="hidden" value="{{TOKEN}}">
in your HTML, then replace the {{TOKEN}} string with the token at each request.
Then use JS like:
var token = $("input#csrf_token").val();
to get the value in your client script.
Edit: I haven't used it myself, but nowjs (http://nowjs.com/) is a more general way of getting your server's variables to the client. It's probably not what you want for passing a simple token, but it might be of interest.

Related

how to render a file and send data to page in the same GET request

I am using angularjs on client-side and experss.js in server-side , i want to render a page and send data to the page (to fill a table) in the same get request
i tried using ejs engine to fill the table in the server-side and then render the page , but the problem with this solution is that the client-side (angularjs) cant access or manipulate the data.
other solution is (atrivial one) is to
make get request to get the page on cient-side
render the page on server-side
make another get request from client-side to get the data
send the data from server to client
The problem with this is that it contains two get requests.
Is there a possible way to render the page and send the data in one get request?
I am doing this to make the loading on site more efficient. Can i acheive more efficiency with one GET request ?
No, you can't. You can only have a single response to a given request. The browser is either expecting an HTML document or it is expecting JSON, it doesn't make sense to give it both at once. but you could render the page and send the data at the same time:
res.render('reports',{data:json});
and then access those data in the newly rendered page.
alternatively you could send a flag when making the call , and then decide whether you want to render or send based on this flag.
Or Ideally, it needs to be 2 separate route, one spitting json and other rendering a view. Else, you could pass a url param, depending on which you return json or render a view.
router.get('/reports/json', function(req,res){
var data = JSON_OBJECT;
res.send(data);
});
router.get('/reports', function(req,res){
var data = JSON_OBJECT;
res.render('path-to-view-file', data);
});
To access data in an AngularJS app without a second server request, include a .value script:
<script>
angular.module("myApp").value("myData",
<JSON data here>
}
</script>
Then in the controller, inject it:
app.controller("myCtrl", function($scope, myData) {
$scope.data = myData;
})
For more information, see
AngularJS angular.module API Reference - .value method
Could you please try using rout.getparam and pass values in route in the get request

Exposing a node.js variable to the client

I would like to expose a node.js server variable to the client. I am trying to get express-expose to work.
I am not sure how to initialise and use that library.
In the express-expose guide the usage doesn't make sense
var express = require('express');
var expose = require('express-expose');
app = expose(app);
app.expose(...);
how can I use app in 'expose(app') before it was initialised ?
I used
const app = expose(express());
app.expose('var some = "variable";','head');
but that doesn't seem to work either.
Can anyone supply me please with an example that initialises the express-expose library and exports var 'some' to the client ?
(By exposing to the client I mean it will be available to all my javascript files as a global variable so that I could do 'console.log(some);' and it would print its value)
Using Pug
Since you're using Express with Pug, you can just call the res.render function and give it the variable you want. Here's how to do that.
Let's say you have a template called index.pug, it may look like this:
html
head
title= title
body
h1= message
On your server, the code responsible for the rendering should look like this. In this case we're passing someVariable to the view that needs to be rendered.
const someVariable = 'hello world!';
app.get('/', function (req, res) {
res.render('index', { title: 'Hey', message: someVariable })
})
A note on express-expose
The express-expose library is not maintained and hasn't been updated in 5 years. My advice would be to just render your variable as described previously or just use AJAX requests.
A note on using a global variable
I am using the 'pug' view engine. It is passed to the view but I want
it as a global javascript variable.
A better idea is to use Template Inheritence to create "generic layouts" and extend them as needed. Sharing a global variable with file you're rendering will not update it magically on the front-end if you're changing it in the back-end. Even if the variable is global.
If you want to reflect "real-time changes" you should look into Socket.io.
This seems like a code smell... But regardless, there are cleaner ways to do it.
If you want to expose a data object, that is, an object just containing keys and values, you could embed it in the rendered webpage, make it available via some API endpoint that the client can acquire via an AJAX request, or expose a raw Javascript file that can be included via <script> (or I guess script(...) in pug).
If you want to expose a more complex Javascript object, such as a class or an object with function definitions, you could expose the Javascript file and include it via script(...).
However, you should be very careful exposing a file used by the server. If there are any vulnerabilities, they are now public. If there are any hard-coded passwords (which shouldn't be in code anyway), they are now public. Anything in this file is now public, so if you do indeed want to do this, be very careful about what code gets into this now client-side file.
If you need more details on how this could work, please comment :)
Edit: Also be aware that using the embedded and include methods would not allow the variable to be updated on-the-fly. If you need the client to track any changes to the data as it changes on the server, you will want to use AJAX. This is the best method, in my opinion. It offers you the most flexibility.
Another edit: Judging by the issues on the express-expose project, it seems not well supported and maybe has security issues. For now, I would avoid it. Maybe at a later time, it will be helpful and secure.
If you want to expose a variable value to the client from server , that never changes or updates, you can simply add a hidden input field in your template and add the value of it
In your EJS template file this would look like
<% if (data) { %>
<input type="hidden" value="<%= data %>" id="myGlobal"/>
<% } %>
you must pass the data value in your res.render('template',{data:"hello"}) function to the template.
You can access this variable value from client using a simple document.getElementById("myGlobal").Again don't pass any sensitive information in hidden fields.
If you want to pass sensitive information , implement an endpoint in your server with authentication and call the endpoint from client via an ajax call .This is also a best approach to update the value of the variable from client side.

How can I send information from NodeJS server to client side?

For example, I want to signal to the client side that a username sent via the POST method in an HTML form already exists in my database.
I know how to recuperate POST data with body-parser and I know how to look it up in a MySQL database.
I know that I could use Ajax to write an error message directly on the form. What does my NodeJS server need to send and how does it send this information?
I've searched through numerous tutorials and I just found solutions where they send a new HTML page. I want to keep my web page the same and use functions like appendChild() to post the error message.
There are a couple of ways you could send data from server-side, so NodeJS, to client-side - which I assume in your case would be some JavaScript file like main.js that handles DOM manimulation.
So, the 1st way you could send data is through a templating engine like Handlebars, for example. There is an easy to use module for express you could get here: hbs.
Now to quickly summarize how an engine like that works, we are basically sending an HTML file like you probably saw in the tutorials, however, a templating engine like Handlebars allows us to send actual data with that file dynamically, so what we would do is render a specific Handlebars template (which in core is just HTML), and pass in a JavaScript object to the render call which would contain all the data you want to pass into that file and then access it in the .hbs file.
So on the server-side, we would write something like this, assuming we have a file called home.hbs and set up Handlebars as the templating engine:
router.get('/home', function(req,res) {
var dataToSendObj = {'title': 'Your Website Title', 'message': 'Hello'};
res.render('home',dataToSendObj);
});
And access in home.hbs like this:
<html>
<header>
{{title}}
</header>
<body>
message from server: {{message}}
</body>
</html>
Now, the issue with this approach is that if you wanted to update the data on the page dynamically, without having to reload the page, using a templating engine would not be ideal. Instead, like you said, you would use AJAX.
So, the 2nd way you could send data from your NodeJS server to the front-end of your website, is using an asynchronous AJAX call.
First, add a route to whatever route handler you are using for AJAX to make a call to. This where you have some logic to perhaps access the database, make some checks and return some useful information back to client.
router.get('/path/for/ajax/call', function(req,res) {
// make some calls to database, fetch some data, information, check state, etc...
var dataToSendToClient = {'message': 'error message from server'};
// convert whatever we want to send (preferably should be an object) to JSON
var JSONdata = JSON.stringify(dataToSendToClient);
res.send(JSONdata);
});
Assuming you have some file such as main.js, create an AJAX request with callbacks to listen to certain event responses like this:
var req = new XMLHttpRequest();
var url = '/path/for/ajax/call';
req.open('GET',url,true); // set this to POST if you would like
req.addEventListener('load',onLoad);
req.addEventListener('error',onError);
req.send();
function onLoad() {
var response = this.responseText;
var parsedResponse = JSON.parse(response);
// access your data newly received data here and update your DOM with appendChild(), findElementById(), etc...
var messageToDisplay = parsedResponse['message'];
// append child (with text value of messageToDisplay for instance) here or do some more stuff
}
function onError() {
// handle error here, print message perhaps
console.log('error receiving async AJAX call');
}
To summarize the above approach using AJAX, this would be the flow of the interaction:
Action is triggered on client-side (like button pressed)
The event handler for that creates a new AJAX request, sets up the callback so it knows what to do when the response comes back from the server, and sends the request
The GET or POST request sent is caught by our route handler on the server
Server side logic is executed to get data from database, state, etc...
The new data is fetched, placed into a JSON object, and sent back by the server
The client AJAX's event listener for either load or error catches the response and executes the callback
In the case of a successful response load, we parse the response, and update the client-side UI
Hope this is helpful!

Access custom request headers node express

I am building a web api with Express and have not found information on accessing incoming custom request headers.
I will be expecting, for instance, that an incoming post request have a provider_identifier header. When I receive the request, I need to access that header information to validate their subscription.
Can someone point me in the right direction/provide advice on this?
router.post('myendpoint/', function(req, res){
var providerId = req.????;
});
Answering my own question here... was kindof a DUH moment for me.
Using above example, simply reference the headers collection like so:
var providerId = req.headers.provider_identifier;
One note: Use an underscore rather than a dash. "provider-identifier" doesn't work, but "provider_identifier" does.

Does the request object in Node.js contain any navigator.userAgent type of information?

I've setup a Node.js server that gets some contact form data and forwards it to my email. I'd like to be able to forward some information about the user's browser along with the form data.
Is any of that information contained in the request object in some form ? Kind of like the navigator.userAgent string that is available on the client ?
Or should I include that string in the data sent out, manually, myself?
I was thinking of something like :
var httpServer = http.createServer(function (request, response)
{
var browserID = request.navigator.userAgent;
});
Thanks!
I was testing this out myself in express, and you can find the user-agent string in:
request.header['user-agent']
and you can see it in the HTTP specification in 14.43 here.
In the future, you can simply examine the request object either with console.log() or with the debugger and see exactly what's in it. I find that is often ultimately more educational than trying to find things in documentation somewhere.

Resources