ANDRIY DACENKO

SOFTWARE ENGINEER

September 9, 2015

EXPRESS.JS - A NODE.JS WEB FRAMEWORK

 BUILD API IN SECONDS

JS MENTORING 2015

WEB FRAMEWORK

Request

DATA

Handle

Get

Provide

Compile

Response

ITS ALL ABOUT

API

Request

Response

Render

express()

var express = require('express');
var app = express();

var root = 'public';
var options = {
  index: 'main.html',
  maxAge: '1d'
};

app.use(express.static(root, options));

app.use('/static', express.static('media'));

SETTINGS

var express = require('express');
var app = express();

app.get('env');
// => development

app.set('token', 'express');

app.get('token');
// => express

app.locals

app.locals.title = 'My App';
app.locals.fs = require('fs');
app.locals.email = 'me@myapp.com';

app.locals.title
// => 'My App'

app.locals.fs
// => {...}

app.locals.email
// => 'me@myapp.com'

Hello World!

var express = require('express');
var app = express();

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

app.listen(3000);

app in app

var admin = express();

admin.get('/', function (req, res) {
  console.log(admin.mountpath); 
  // => [ '/adm*n', '/manager' ]
  res.send('Admin Homepage');
})

var secret = express();
secret.get('/', function (req, res) {
  console.log(secret.mountpath); 
  // => /secr*t
  res.send('Admin Secret');
});

admin.use('/secr*t', secret);
app.use(['/adm*n', '/manager'], admin);

ROUTING

app.get('/', function (req, res) {
  res.send('GET request to homepage');
});
app.post('/', function (req, res) {
  res.send('POST request to homepage');
});
app.put('/', function (req, res) {
  res.send('PUT request to homepage');
});
app.delete('/', function (req, res) {
  res.send('DELETE request to homepage');
});

METHOD

app.METHOD(path, callback [, callback ...])
  • 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

ROUTE PATHS

path = 'hello';

path = 'hello*world';

path = /^hello\-world$/
// will match acd and abcd
'ab?cd'
// will match abcd, abbcd, abbbcd, and so on
'ab+cd'
// will match abcd, abxcd, abRABDOMcd, and so on
'ab*cd'
// will match abe and abcde
'ab(ce)?d'

ROUTE PARAMS

var express = require('express');
var app = express();

app.param('id', function (req, res, next, value) {
  console.log('id = ', value);
  next();
});

app.get('/user/:id', function (req, res, next) {
  console.log('this matches');
  next();
});

app.get('/user/:id/:page', function (req, res) {
  console.log('and this matches too');
  res.end();
});

app.listen(9090);

ROUTER

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

products.route('/products')
  .all(function(req, res, next) {
    // pre validate request
  })
  .get(function(req, res, next) {
    res.json(...);
  })
  .post(function(req, res, next) {
    // add a new product...
  });

app.use(products);

REQUEST

query

parameters

body

HTTP headers

REQ.APP

var express = require("express");
var app = express();

app.get("/views", function (req, res) {
  console.log(req.app.get("views"));
});

BASE URL

var express = require("express");
var app = express();

var greet = express.Router();

greet.get('/jp', function (req, res) {
  console.log(req.baseUrl); // /greet
  res.send('Konichiwa!');
});

app.use('/greet', greet);

BODY

var app = require('express')();
var bodyParser = require('body-parser');
var multer = require('multer'); 

// for parsing application/json
app.use(bodyParser.json());
// for parsing application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ 
  extended: true
}));
// for parsing multipart/form-data
app.use(multer());
app.post('/', function (req, res) {
  console.log(req.body);
  res.json(req.body);
});

MISC

req.cookies.name
// => "john_doe"

// Host: "example.com:3000"
req.hostname
// => "example.com"

req.port
// => 3000

req.ip
// => "127.0.0.1"

// GET /user/john_doe
req.params.name
// => "john_doe"

// example.com/users?name=john_doe
req.path
// => "/users"
req.protocol
// => "https"

// GET /search?q=tobi+ferret
req.query.q
// => "tobi ferret"

// GET /shoes?order=desc&shoe[color]=blue
req.query.order
// => "desc"

req.query.shoe.color
// => "blue"

// Host: "mobile.api.example.com"
req.subdomains
// => ["api", "mobile"]

req.xhr
// => true

ACCEPTS

app.get('/hello', function(req, res) {
  switch(req.accepts(['json', 'html'])) {
    case 'json':
      res.setHeader('Content-Type', 'application/json')
      res.write('{"hello":"world!"}')
      break
    case 'html':
      res.setHeader('Content-Type', 'text/html')
      res.write('<b>hello, world!</b>')
      break
    default:
      // the fallback is text/plain
      res.setHeader('Content-Type', 'text/plain')
      res.write('hello, world!')
      break
  }

  res.end();
});

RESPONSE

body

files

coockies

HTTP headers

PROPS

var express = require('express');
var app = express();

app.get('/views', function (req, res) {
  console.log(res.app.get('views'));

  res.locals.user = req.user;
  res.locals.authenticated = !req.user.guest;
});

app.get('/', function (req, res) {
  console.log(res.headersSent); // false
  res.send('OK');
  console.log(res.headersSent); // true
})

SEND

res.send(new Buffer('whoop'));
res.send({ some: 'json' });
res.send('<p>some html</p>');

res.status(404)
  .send('Sorry, we cannot find that!');

res.status(500).send({ 
  error: 'something blew up' 
});

SEND FILE

app.get('/user/:uid/photos/:file', function(req, res){
  var uid = req.params.uid
    , file = req.params.file;

  req.user.mayViewFilesFrom(uid, function(yes){
    if (yes) {
      res.sendFile('/uploads/' + uid + '/' + file);
    } else {
      res.status(403).send('Sorry! you cant see that.');
    }
  });
});

DOWNLOAD

res.download('/img-123.pdf');

res.download('/img-123.pdf', 'img.png');

res.download('/img-123.pdf', 'img.png', function(err){
  if (err) {
    // Handle error, but response may be partially-sent
    // so check res.headersSent
  } else {
    // decrement a download credit, etc.
  }
});

JSON(P)

res.json(null)
res.json({ user: 'tobi' })
res.status(500).json({ error: 'message' })

// ?callback=foo
res.jsonp({ user: 'john' })
// => foo({ "user": "john" })

app.set('jsonp callback name', 'cb');

// ?cb=foo
res.status(500).jsonp({ error: 'message' })
// => foo({ "error": "message" })

FORMAT

res.format({
  text: function(){
    res.send('hey');
  },

  html: function(){
    res.send('<p>hey</p>');
  },

  json: function(){
    res.send({ message: 'hey' });
  }
});

COOKIES

res.cookie('name', 'john', { path: '/admin' });
res.clearCookie('name', { path: '/admin' });

res.cookie('name', 'john', { signed: true });
req.signedCookie('name'); 
// => john

res.cookie('name', 'john', { 
  domain: '.example.com', 
  path: '/admin', 
  secure: true 
});

res.cookie('rememberme', '1', { 
  expires: new Date(Date.now() + 900000), 
  httpOnly: true 
});

REDIRECT

res.redirect('/foo/bar');

res.redirect('http://example.com');

res.redirect(301, 'http://example.com');

res.redirect('../login');

res.redirect('back');

SET HEADERS

res.set('Content-Type', 'text/plain');

res.set({
  'Content-Type': 'text/plain',
  'Content-Length': '123',
  'ETag': '12345'
});

res.append('Link', ['<http://localhost/>', '<http://localhost:3000/>']);
res.append('Set-Cookie', 'foo=bar; Path=/; HttpOnly');
res.append('Warning', '199 Miscellaneous warning');

HEADERS ALIASES

res.attachment();
// Content-Disposition: attachment

res.attachment('path/to/logo.png');
// Content-Disposition: attachment; filename="logo.png"
// Content-Type: image/png

res.links({
  next: 'http://api.example.com/users?page=2',
  last: 'http://api.example.com/users?page=5'
});

// Link <http://api.example.com/users?page=2>; rel="next", 
//      <http://api.example.com/users?page=5>; rel="last"
res.location('/foo/bar');
res.location('http://example.com');
res.location('back');

res.type('.html');              // => 'text/html'
res.type('html');               // => 'text/html'
res.type('json');               // => 'application/json'
res.type('application/json');   // => 'application/json'
res.type('png');                // => 'image/png'

res.sendStatus(200); // res.status(200).send('OK')
res.sendStatus(403); // res.status(403).send('Forbidden')
res.sendStatus(404); // res.status(404).send('Not Found')
res.sendStatus(500); // res.status(500).send('Internal Server Error')

res.sendStatus(2000); // res.status(2000).send('2000')

RENDERING

var app = express();

app.set('views', './views');
app.set('view engine', 'jade');

app.get('/', function (req, res) {
  res.render('index', { 
    title: 'Hey', 
    message: 'Hello there!'
  });
});
// index.jade
html
  head
    title!= title
  body
    h1!= message
npm i jade --save

ENGINE

var fs = require('fs');

app.engine('rpl', function (filePath, options, callback) {
  fs.readFile(filePath, function (err, content) {
    if (err) return callback(new Error(err));

    var rendered = content.toString()
      .replace('%title%', '<title>'+ options.title +'</title>')
      .replace('%message%', '<h1>'+ options.message +'</h1>');

    return callback(null, rendered);
  })
});

app.set('views', './views');
app.set('view engine', 'rpl'); 

app.get('/', function (req, res) {
  res.render('index', { 
    title: 'Hey', 
    message: 'Hello there!'
  });
})

MIDDLEWARE

App

Router

Error

Third-party

APP LEVEL

var app = express();

app.use(function (req, res, next) {
  console.log('Time:', Date.now());
  next();
});

app.use('/user/:id', function (req, res, next) {
  console.log('Request Type:', req.method);
  next();
});

app.get('/user/:id', function (req, res, next) {
  res.send('USER');
});

ROUTER LEVEL

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

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');
});

app.use('/', router);

ERRORS

app.use(function(err, req, res, next) {
  console.error(err.stack);

  if (req.app.enabled('debug')) {
    res.status(500).send(err);
  } else {
    next();
  }
});

app.use(function(err, req, res, next) {
  res.status(500).send('Something broke!');
});

LINKS

Q&A Time

ANDRIY DACENKO

SOFTWARE ENGINEER

September 9, 2015

EXPRESS.JS - A NODE.JS WEB FRAMEWORK

 BUILD API IN SECONDS

Express.js - a node.js web framework

By Andrew Dacenko

Express.js - a node.js web framework

Server programming using Node.js Express.js – a node.js web framework

  • 1,316