CORS-enabled Node/Express application and the JQuery client in Netbeans

P.Madhanasekaran

We have earlier seen CORS-enabled JEE REST services. We will see a CORS-enabled Express application now and a little later a similar Asp Net Web API application. What is CORS? A JavaScript application running in one web site can not have access to the resources from another web site. This is due to same-origin policy security restriction imposed by browsers. CORS is a World Wide Web Consortium (W3C) specification (commonly considered part of HTML5) allows JavaScript to overcome this same-origin policy security restriction. Unlike a work-around like JSONP, it is a standard which is implemented in all latest Browsers.

Same Origin policy:

The same-origin policy means that our JavaScript can only make AJAX calls back to the same origin of the containing Web page (where “origin” is defined as the combination of protocol, domain name, and port).In other words the server and the JavaScript client accessing it should be on the same web-site. For example
These two URLs have the same origin:

  • http://example.com/index.html
  • http://example.com/list.html

These URLs have different origins than the previous two:

  • http://example.net - Different domain
  • http://example.com:9000/index.html - Different port
  • https://example.com/index.html - Different scheme
  • http://www.example.com/index.html - Different sub-domain

CORS relaxes this restriction by letting servers indicate which origins are allowed to call them. CORS is enforced by browsers but must be implemented on the server. The basic idea behind CORS is to use HTTP headers.

What is the rule for the client?
The JavaScript code can make HTTP requests with the “XMLHttpRequest” object. It should specify HTTP method (GET, POST etc.) and “url”  to which request should be sent. It should also contain the code to process the response.

How the server uses headers:  Using the response headers, the server can indicate which clients can access the API, which HTTP methods or HTTP headers are allowed, and whether cookies are allowed in the request.  

Role of Browser The browser acts like a trusted intermediary, and plays an active role in a CORS request in two ways:

  • The browser identifies whether the request is a CORS and adds additional information to the request so that the server can identify the client – normally the “Origin” request header.
  • The browser interprets the server’s response and decides whether to send the request to the client or to return an error.

If the browser doesn’t do these things, a client could send any request to the server, and the protection introduced by the browser’s same-origin policy would be broken. The browser ensures that both the client and the server play by the rules of CORS.

Simple and Pre-flight Requests:  A simple request is one that uses either GET or POST or Head method and whose Content-type request header is
a) application/x-www-form-urlencoded
b ) multipart/form-data,
c) text/plain.

In such cases, the Browser adds an extra header called “Origin” to the request. The Origin header contains the origin of the requesting page so that the server can easily determine whether or not it should serve a response. For non-simple requests the browser before making the request has to use a mechanism for prior verification called preflight requests.  Have a look at Figure-1 and Figure-2 and see how the browser and server exchange “origin” headers.

CORS is built around many headers, but the two most important are:

  • The Origin request header.
  • The Access-Control-Allow-Origin response header.

These headers must be present on every successful CORS request. Without one or the other, the CORS request will fail.

The server can either respond with the exact origin value from the request or a value of “*” indicating any origin is allowed. If the server hadn’t allowed the calling origin, then the Access-Control-Allow-Origin header would be absent from the response and the calling JavaScript’s error callback would be invoked. With a simple CORS request the call on the server is still invoked. CORS doesn’t prevent the call from being invoked on the server; rather, it prevents the calling JavaScript from receiving the results.

MongoDB

It is a document-oriented database, fitting in somewhere between Key-Value stores and traditional relational databases. Despite being a document store, MongoDB also enables rich querying and secondary indexing of documents, setting it apart from other NoSQL databases and making it a very powerful option. MongoDB stores documents as BSON, which is effectively binary-encoded JSON. When you run a query you get a JSON object returned (or a string in JSON format, depending on the driver).

” By allowing embedded documents and arrays, the document-oriented approach makes it possible to represent complex hierarchical relationships with a single record. This fits very naturally into the way developers in modern object-oriented languages think about their data .But remember it has no transaction support. Its Schema-free nature makes data migrations unnecessary. But it becomes the look out of the application to point it out – not the DB- when some wrong data is entered. Its document-oriented-nature enables scaling out easy. We have earlier seen MongoDB and its use with many languages- Java, Scala and JavaScript (Node). Go to
(installation directory)/mongodb/bin.

Execute
mongod –dbpath E:\data (path to the data folder you created for the purpose).
The mongodb database server will start.
In another instance of command prompt also
Go to (installation directory)/mongodb/bin

Execute
mongo
This will start the JavaScript mongo client shell.

Execute
show dbs
You can see a list databases available.

Execute
use EmployeeDB ( memory for blogdb will be earmarked, if there is no database by that name).The db will be created only when we actually insert documents)

db.employees.insert({Name: “Venkat”, Department: “Protection” })

The database “EmployeeDB” and the Collection “employees” are created now and a document is inserted; but there will be no indication except that the Command prompt will change to >.
You can insert one more document.

db.employees.insert({Name: “Ganesha”,Department: “Support” })

You can execute
db.employees.find()

and see the documents you  inserted.
Now the MongoDB is ready for use.

Generate Express application

NB has a NodeJS plug-in but it may take some time for it to become a fully mature product. So we do not use it for creating the server side application.  But NB has many features –described in the later part of the article- which make it an excellent IDE for client-side JavaScript applications. So we will use it for creating our client-side application.

Now we can generate an Express application with the command

express  CorsApp (name of application)
in the command prompt change to CorsApp and execute
npm install (to install dependencies)
&
npm install mongoose( we will use Mongoose ODM  with MongoDB ).

As our application will be accessed only by a client from another origin we will delete the generated view layer and other related files. The following folders with files can be deleted:

 

  •  
    • views
    • routes  -linked to view files and we will define “routes” separately.
    • public – js and other files necessary, including css file, for view.
    •  bin- contains the file “www”, in which the Express/Http server is created. We will create the server in the file “app.js” itself.

Before looking at the required modifications in “app.js” we will see other files required.

Mongoose

You know that for NoSQL databases you need not define any schema before storing data, as in a relational database.ie no “pre-defined” schema is necessary as the structure of the Document stored becomes the “schema”. When you use mapping tools like mongoose you have to define a schema before hand and thus lose some of the dynamism of MongoDB. As the schema is defined in the application and not in the DB, migration of large scale data is not necessary. Mapping tools are useful because they help programmers to understand the contents of the database and implicit rules for working with domain data. They also provide them with some convenient methods to interact with MongoDB. It allows you to define a schema for your data, so that you can interact with your MongoDB data in a structured and repeatable way. Mongoose helps with many common MongoDB tasks, and removes some of levels of complexity from the nested callbacks you have to employ, while using the native MongoDB driver. Mongoose also returns the data to you as a JSON object that you can use directly, rather than the JSON string returned by MongoDB. Mongoose also has a whole suite of helper functions and methods. As we will see, Mongoose is an expressive environment that makes models and schemas more intuitive.

The schema is defined in the file “employee.js” code for which is given below:

models/employee.js

var mongoose = require('mongoose');
var schema = new mongoose.Schema({Name: String, Department: String});
module.exports = mongoose.model('Employee', schema);  //---1)


1) The mongoose.Schema is defined here and passed to mongoose.model() constructor. Instances of these models represent documents which can be saved and retrieved from our database. All document creation and retrieval from the database is handled by these models. This model is exported as a module for use in other modules that require it.

The module that requires and uses the above module is blogsController.js, the code for which is given below:

empsController.js

var Blog = require('./models/employee');

module.exports.create = function(req,res) {
var employee = new Employee(req.body);
employee.save(function (err,result) {
res.json(result);
});
}
module.exports.list = function(req,res) {
Employee.find({}, function (err,results) {    //--------1)
res.json(results); // json() in res object in Express returns a JSON.
});
}

  • Documents can be retrieved through several static helper methods of models in Mongoose. The method find() is one such method. When a callback function is passed to it, the operation will be executed immediately with the results passed to the callback.

Modifications in app.js

You can modify generated app.js as under:

app.js

var express = require('express');
/* represents an instance of Express and most of the functionality is provided by invoking the methods and properties in Express through this app object */
var app = express(); 
var path = require('path');  // requiring various middlewares starts from here
var favicon = require('serve-favicon');   
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
// code we added for the use of mongoose
var mongoose = require('mongoose');
var blogsController = require('./empsController');
mongoose.connect( 'mongodb://localhost/employeeDB' );
/* configuring  the app to use middlewares */     
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
/* a custom function that adds “Access-Control-Allow-Origin” header to response is passed to app.use() like any other middleware*/
app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*"); /* tells the Browser any origin and any method is allowed */
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");  /* ------1) */
next(); //  response is not rendered here and control goes to next function in line
});
app.get('/api/blogs', empsController.list);  //---2)
app.post('/api/blogs', empsController.create);
var server = require('http').createServer(app);  //creation of Express Server object
server.listen(3000, '0.0.0.0');  
console.log(' [*] Listening on 3000' );

Most of the code retained is for use of Middlewares. As mentioned earlier, we have created the server here itself and deleted the file bin/www generated for the purpose. Code relating to mongoose and Origin has been added. We have deleted the generated code related to error –handling and the code relating to view. Usually Controller sends the response to view which is responsible for displaying in the Browser. As there is a separate client application, no view file is used here.

  • We will use the very same response headers to enable CORS in the ASP Net Web API Rest services later.
  • Route handling .Routes are mapped to handlers i.e. functions. This route ‘api/employeess’ will be handled by the list() method in empsController. Routes in Express are defined using methods named after the HTTP verbs, on an instance of an Express application. Here the list(), from empsController module is required and used. It, as we saw above, returns a “JSON” object. In other words, a “RESTful” API has been provided.

Client file in NB:


Why should you use NetBeans as a JavaScript IDE? NB has a NodeJS plug-in but it may take some time for it to become a fully mature product. So we did not use it for creating the server side application. But NB has many features that make it an excellent IDE for client-side JavaScript applications.

  • Syntax coloring and code highlighting for methods and variables, as well as global variables and code folding.
  • A parser that runs in the background and provides detailed warnings and hints to resolve potential problems. You can configure the JavaScript hints that are displayed in the Hints tab in the Options window.
  • Code completion will show you the methods available for all the literal types in JavaScript.
  • NetBeans IDE consults type parameters for function parameters and return types (@type, @param). These types are shown in code completion.
  • To debug the JavaScript files you can install the NetBeans Connector extension for the Chrome browser. Debugging is enabled automatically when you run the application in the browser and the extension is installed.
  • Itenables you to easily configure and run unit tests on JavaScript files using the Jasmine testing framework and the Karma or the JS Test Driver test runner.

The articles “Editing JavaScript” & “Debugging and Testing JavaScript in an HTML5 Application” available on NetBeans.org may be seen to understand the full potential of NB as a JavaScript IDE. The fact is that there is no better or even equal Open-source IDE for JavaScript. WebStorm from JetBrains, Komodo IDE and Visual Studio 2013 are commercial products. SublimeText is a good editor. Eclipse with JSDT (JavaScript Development Tools) seems to lag behind. They say incorrect code diagnostics and lack of code folding are its main problems. Attention is invited to the article “WebStorm and Sublime Text lead a field of diverse and capable tools for JavaScript programming” on Java World.com.

Create a HTML-5 Application:

You can create HTML-5 application in NetBeans ( version.7.3 and above).You know a HTML-5 application can be accessed by a Browser in a variety of devices, including smart-phones, tablets and laptops. The application typically uses HTML + JavaScript + CSS. In NB-7.4 go to FileàNew Project and in the New Project Wizard select HTML5 under Categories and HTML5 Application under Projects and click Next. In the New HTML5 Application Wizard that follows give the Project Name as NodeClient”and click “Next”. In the Next Wizard you will be asked “whether you want to initialize the project structure with a site template” and the option “No Site Template” would have been selected. Click Next. In the Wizard that follows select in Library jquery version 2.0.3 and Click the button containing the symbol > and it will be added to the Selected box as in Figure-2. Click Finish. JQuery will be downloaded and the project structure will be created by the IDE. You can fill up index.html as shown below:

index.html

<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript" src="js/libs/jquery/jquery.js"></script>
</head>
<body>
<script type="text/javascript">
$(document).ready(function () {
$('#search').click(function () {
$('#employees').empty();
$.getJSON("http://localhost:3000/api/employees", function (data) {
$.each(data, function (i, employee) {

                        var content =   employee.Name + ' ' + employee.Department ;

                        $('#employees').append($('<li/>', { text: content }));
});
});
});
});
</script>

<div>
<div>
<h1>Employees Listing</h1>
<input id="search" type="button" value="Get" />
</div>
<div>
<ul id="employees"></ul>
</div>   
</div>
</body>

 If you compare the above JavaScript code to the “index.cshtml” in the earlier Asp Net Web API article, you will find no difference. We will use this HTMl-5 project created in NetBeans to access the CORS-enabled Rest Services from ASP Net Web API later. You may wonder where is the XMLHttpRequest Object? JQuery has a $.ajax() function which invokes the above object underneath. $getJSON() is only short-hand notation for the $.ajax().It tells the method is “GET” and the data from the server is “JSON”. Look at the parameters. A) “url”  B) the callback function to process the response - to be executed whenever the data is loaded successfully. The comments are repeated here also for sake of convenience.

  •  JQuery is a tool for manipulation of DOM elements. The Code segment given within the $(document).ready () will execute when the document is ready (i.e., when the page content is loaded and DOM is created). To ensure that the manipulation starts only after that, the entire code is put within $(document).ready ().
  • There are two <div> in the page. The first <div> contains a button -id “search”, on the click of which the data from the server is loaded and the callback function is triggered.
  • The second <div> contains an unordered list to which the data obtained from Node/Express is appended.
  • See note 2) above.
  • As mentioned above, the Express api url and a callback function are passed to the function getJSON() in JQuery.
  • Within the above callback function , each() in  JQuery-  similar to “forEach” in other languages  is used to fetch and append the data to the unordered list “employees”.
  • As mentioned above, jQuery is meant for manipulating DOM elements. Here the data fetched is appended to the element “employees”.

As mentioned in earlier articles JQuery, is more widely-used than SPA frameworks like Angular or Backbone; but the SPA frameworks have their own advantages, especially when you want to add more features to your application. For example if you want your client not only to “GET” but also to “POST” data,  then Angular with its automatic “two way” data-binding is more suitable. From Angular version 1.2, no special code is required to make a CORS request. We will see the steps required to create an Angular client in NetBeans for our Node Rest API and Asp Net Web API in the next  the article. As you will see, we can use the same code in the Angular client also to access the REST services from these different technologies, by simply changing the port numbers in which these services run.

Conclusion

CORS is a part of HTML-5 that has support in all newer Browsers.IE users have to choose version-10 and above for full CORS support. Earlier, techniques like JSONP were used to overcome Browser restrictions on cross-origin requests. Node + Express application is easy to create and we can attach the extra Response header “Access-Control-Allow-Origin” in code through a callback passed to app.use(). NetBeans is an excellent open-source JavaScript IDE, especially for HTML-5. It helps you to download and use JavaScript library of your choice from the numerous ones available -JQuery, Angular, backbone, Ember etc. The HTML-5 app can be accessed from Browsers in mobiles also. NB has good editing features for JavaScript like code completion and a back-ground parser to point out potential problems. You can use debugging in Chrome through “NetBeans-Connector”. NB comes with Testing Tools like Jasmine and Karma. So it is a better tool for creating the client applications in JavaScript whether for the Restful Express/Node application or a RESTful web service from JVM or Dot Net. We will see more of this in future.








}