Express

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

With a myriad of HTTP utility methods and middleware at your disposal, creating a robust API is quick and easy.

Express provides a thin layer of fundamental web application features, without obscuring Node features that you know and love.

Source: Express.js

Author of Express.js

TJ Holowaychuk

Quick Start

  • Install express with npm

 

 

  • "Hello World"

 

 

 

  • Run
  • View in browser

 

  • Get
$ npm install express --save
// FILENAME: app.js
var express = require('express');
var app = express();

app.get('/', function (req, res) {
  res.send('Hello World!');
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});
$ node app.js
Example app listening at http://localhost:3000

Routing

Glossary

  • Routing refers to the definition of end points (URIs) to an application and how it responds to client requests.

 

  • In Express.js, a route is a combination of a URI, a HTTP request method (GET, POST, and so on), and one or more handlers for the endpoint.

 

  • It takes the following structure app.METHOD(path, [callback...], callback), where app is an instance of express, METHOD is an HTTP request method, path is a path on the server, and callback is the function executed when the route is matched.

Source: Routing

Routing Method

  • checkout
  • connect
  • copy
  • delete
  • get
  • head
  • lock
  • merge
  • mkactivity
  • mkcol
  • move
  • m-search
  • notify
  • options
  • patch
  • post
  • propfind
  • proppatch
  • purge
  • put
  • report
  • search
  • subscribe
  • trace
  • unlock
  • unsubscribe

Source: Express API

app.METHOD(path, callback [, callback ...])

  • Express supports the following routing methods corresponding to the HTTP methods of the same names:

Routing Path

  • Routing paths can be string patterns or regular expression with extracted parameters starting with colon ( : ). 
  • The extracted parameters are loaded automatically as properties of req.params.*

Source: Routing Paths

Path Type Params Examples
"/path" string pattern   /path
"/path/ab*cd" string pattern   abcd, abxcd, abxxcd, abccd etc.
"/profile/:id" string pattern id /profile/xxx, /profile/1234, /profile/abcd-1234
/\.md$/ regular expression   /abcd.md, /path/1234.md; *NOT* match /abc.md/1234

Routing Handlers

  • You can provide multiple callback functions that behave just like middleware to handle a request
  • Route handlers can come in the form of a function, an array of functions, or various combinations of both
var cb0 = function (req, res, next) {
  console.log('CB0');
  next();
}

var cb1 = function (req, res, next) {
  console.log('CB1');
  next();
}

var cb2 = function (req, res) {
  res.send('Hello from C!');
}

app.get('/example/c', [cb0, cb1], cb2);

Basic Route Examples

// ROUTE - A
app.get('/', function(req, res) {
  res.send('hello world');
});

// ROUTE - B
app.post('/', function (req, res) {
  res.send('POST request to the homepage');
});

// ROUTE - C
app.get('/about', function (req, res) {
  res.send('about');
});

// ROUTE - D
app.get('/ab*cd', function(req, res) {
  res.send('ab*cd');
});
// ROUTE - E
app.get(/.*fly$/, function(req, res) {
  res.send('/.*fly$/');
});

// ROUTE - F
app.get('/path/:id', function(req, res) {
  res.send('/path/' + req.params.id);
});

// ROUTE - G
app.post('/ab(cd)?e', function (req, res) {
  res.send('ab(cd)?e');
});

// ROUTE - H
app.get('/example/b', function (req, res, next) {
  console.log('response will be sent by' +
            ' the next function ...');
  next();
}, function (req, res) {
  res.send('Hello from B!');
});

Response

Method Description
res.download() Prompt a file to be downloaded.
res.end() End the response process.
res.json() Send a JSON response.
res.jsonp() Send a JSON response with JSONP support.
res.redirect() Redirect a request.
res.render() Render a view template.
res.send() Send a response of various types.
res.sendFile() Send a file as an octet stream.
res.sendStatus() Set the response status code and send its string representation as the response body.

Source: Routing

Middleware

Glossary

  • Middleware is a function with access to the request object (req), the response object (res), and the next middleware in the application’s request-response cycle, commonly denoted by a variable named next.

 

  • Middleware can
    • Execute any code.
    • Make changes to the request and the response objects.
    • End the request-response cycle.
    • Call the next middleware in the stack.

Middleware Pattern

Application-level Middleware

var app = express();

// a middleware with no mount path;
// gets executed for every request to the app
app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// a middleware mounted on /user/:id;
// will be executed for any type of HTTP request to /user/:id
app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

// a route and its handler function (middleware system)
// which handles GET requests to /user/:id
app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

Bind application-level middleware to an instance of the app object with app.use() and app.METHOD(), where METHOD is is the HTTP method of the request that it handles, such as GET, PUT, POST, and so on, in lowercase.

Router-level Middleware

var app = express();
var router = express.Router();

// a middleware with no mount path, gets executed
// for every request to the router
router.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

// a middleware sub-stack shows request info for
// any type of HTTP request to /user/:id
router.use('/user/:id', function(req, res, next) {
  console.log('Request URL:', req.originalUrl);
  next();
}, function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

Router-level middleware works just like application-level middleware except it is bound to an instance of express.Router().

// a middleware sub-stack which handles GET
// requests to /user/:id
router.get('/user/:id', function (req, res, next) {
  // if user id is 0, skip to the next router
  if (req.params.id == 0) next('route');
  // else pass the control to the next middleware
  // in this stack
  else next();
}, function (req, res, next) {
  // render a regular page
  res.render('regular');
});

// handler for /user/:id which renders a special page
router.get('/user/:id', function (req, res, next) {
  console.log(req.params.id);
  res.render('special');
});

// mount the router on the app
app.use('/', router);

Builtin Middlewares

Property Description Type Default
dotfiles Option for serving dotfiles. Possible values are “allow”, “deny”, and “ignore” String “ignore”
etag Enable or disable etag generation Boolean true
extensions Sets file extension fallbacks. Array []
index Sends directory index file. Set false to disable directory indexing. Mixed “index.html”
lastModified Set the Last-Modified header to the last modified date of the file on the OS. Possible values are true or false. Boolean true
maxAge Set the max-age property of the Cache-Control header in milliseconds or a string in ms format Number 0
redirect Redirect to trailing “/” when the pathname is a directory. Boolean true
setHeaders Function for setting HTTP headers to serve with the file. Function
var options = {
  dotfiles: 'ignore',
  etag: false,
  extensions: ['htm', 'html'],
  index: false,
  maxAge: '1d',
  redirect: false,
  setHeaders: function (res, path, stat) {
    res.set('x-timestamp', Date.now());
  }
}

app.use(express.static('public', options));

Third-Party Middlewares

  • List of third-party middlewares
    • body-parser: populate the req.body property with the parsed body or provide an error to the callback
    • cookie-parser: Parse Cookie header and populate req.cookies with an object keyed by the cookie names. 
    • cookie-session: Simple cookie-based session middleware.
  • Example - use cookie-parser
$ npm install cookie-parser
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');

// load the cookie parsing middleware
app.use(cookieParser());

WebSocket

WebSocket is a protocol providing full-duplex communication channels over a single TCP connection.

 

The WebSocket API is a Candidate Recommendation of W3C standard.

WebSocket Demo - Echo

  • Open up WebSocket connection
    •  
    • ws: - protocol of WebSocket for unencrypted transportation; and wss: protocol is used for encrypted transportation like https:
    • ['soap', 'xmpp'] - optional subprotocols on IANA registry
  • Listen to the event handlers

 

 

 

 

 

  • Send message to server

Source:

var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);
// When the connection is open, send some data to the server
connection.onopen = function () {
  connection.send('Ping'); // Send the message 'Ping' to the server
};

// Log errors
connection.onerror = function (error) {
  console.log('WebSocket Error ' + error);
};

// Log messages from the server
connection.onmessage = function (e) {
  console.log('Server: ' + e.data);
};
// Sending String
connection.send('your message');

WebSocket Protocol - 13 RFC6455

  • Client sends handshake message to server:

 

 

 

 

  • and server responses with following:

 

 

 

  • then keep connection and exchange data in frames
  • ... until connection closed

Source: RFC6455

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat

Relationship to TCP and HTTP

  • The WebSocket Protocol is an independent TCP-based protocol. Its only relationship to HTTP is that its handshake is interpreted by HTTP servers as an Upgrade request.

 

  • By default, the WebSocket Protocol uses port 80 for regular WebSocket connections and port 443 for WebSocket connections tunneled over Transport Layer Security (TLS) [RFC2818].

Source: RFC6455

WebSocket on Server Side

Source: WS

var WebSocketServer = require('ws').Server
  , wss = new WebSocketServer({ port: 8080 });

wss.on('connection', function connection(ws) {
  ws.on('message', function incoming(message) {
    console.log('received: %s', message);
  });

  ws.send('something');
});

A Chat Server

Source: Why Use Node.js

RESTful Web Service

Representational State Transfer

Glossary

  • REST defines a set of architectural principles by which you can design Web services that focus on a system's resources, including how resource states are addressed and transferred over HTTP by a wide range of clients written in different languages.
  • RESTful web service follows four basic design principles
    • Use HTTP methods explicitly.
    • Be stateless.
    • Expose directory structure-like URIs.
    • Transfer XML, JavaScript Object Notation (JSON), or both.

Use HTTP methods explicitly

  • REST asks developers to use HTTP methods explicitly and in a way that's consistent with the protocol definition. This basic REST design principle establishes a one-to-one mapping between create, read, update, and delete (CRUD) operations and HTTP methods.
  • According to this mapping:
    • To create a resource on the server, use POST.
    • To retrieve a resource, use GET.
    • To change the state of a resource or to update it, use PUT.
    • To remove or delete a resource, use DELETE.

Be stateless

  • A complete, independent request doesn't require the server, while processing the request, to retrieve any kind of application context or state.
  • A REST Web service application (or client) includes within the HTTP headers and body of a request all of the parameters, context, and data needed by the server-side component to generate a response.
  • Statelessness in this sense improves Web service performance and simplifies the design and implementation of server-side components because the absence of state on the server removes the need to synchronize session data with an external application.

Be stateless - Example

Stateful Web Service

Stateless Web Service

Expose directory structure-like URIs

  • REST Web service URIs should be intuitive to the point where they are easy to guess. The structure of a URI should be straightforward, predictable, and easily understood.
  • One way to achieve this level of usability is to define directory structure-like URIs.

 

  • Some additional guidelines to make note of while thinking about URI structure for a RESTful Web service are:
    • Hide the server-side scripting technology file extensions (.jsp, .php, .asp), if any, so you can port to something else without changing the URIs.
    • Keep everything lowercase.
    • Substitute spaces with hyphens or underscores (one or the other).
    • Avoid query strings as much as you can.
    • Instead of using the 404 Not Found code if the request URI is for a partial path, always provide a default page or resource as a response.

http://www.myservice.org/discussion/{year}/{day}/{month}/{topic}

Transfer XML, JSON, or both

  • The last set of constraints that goes into a RESTful Web service design has to do with the format of the data that the application and service exchange in the request/response payload or in the HTTP body. This is where it really pays to keep things simple , human-readable , and connected .
  • Common MIME types used by RESTful services
MIME-Type Content-Type
JSON application/json
XML application/xml
XHTML application/xhtml+xml

Questions?

What we learned

  • Express - a lightweight web application framework for Node.js

  • WebSocket - a protocol for persistent full-duplex TCP communication

  • RESTful - principles of developing web services

Source: Why Git?

Server Side JavaScript - Node.js (Part2)

By Haili Zhang

Server Side JavaScript - Node.js (Part2)

  • 1,208