Web development

More core

Application development (Express JS)

Middleware (Connect)

But first...

let's recap

Hello world

...as an http server

var http = require('http');

var server = http.createServer(function(req, res){
	res.writeHead(200, {'content-type':'application/json'});
	res.end('{"hello": "world"}');
});

server.listen(3000);

ORC Client

var net = require('net');
var stdin = process.openStdin();

var client = net.connect('3000', 'localhost');
client.setEncoding('utf8');

client.on('connect', function(){
	stdin.addListener("data", function(d) {
		client.write(d.toString().substring(0, d.length-1));
	});
});

client.on('data', function(data){
	data = data.toString().replace('\r\n', '');
	console.log(data);
});

Shared State

var http = require('http');

var count = 0;

var server = http.createServer(function(req, res){
    console.log(req.url + " " + count);
    res.end('Visitor number: ' + count++);
});

server.listen(3000);

Streams

var http = require('http');
var fs = require('fs');

http.createServer(function(req, res){

    if(req.url === "/"){
        var fileStream = fs.createReadStream('package.json', {'encoding': 'utf8'});
	var myBuffer = "";
	fileStream.on('data', function(fragment){
	    myBuffer += fragment;
        });

        fileStream.on('end', function(theEnd){
	    res.end(myBuffer);
	});

    }else if(req.url === "/image"){
	var fileStream = fs.createReadStream('image.png').pipe(res);

    }else{
	res.end("404 404 404 404 404.....");
    }

}).listen(3000);
  • readStream.on('data', callback)
  • readStream.on('end', callback)
  • readStream.pipe(writeStream)

server responsestreams

On request: Extend prototypes

var events = require('events');

function Person(nameInput){
    this.name = nameInput;
    this.sayMyName = function(preString){
        console.log(preString + this.name);
    }
    events.EventEmitter.call(this);
}

Person.prototype = Object.create(events.EventEmitter.prototype);

var p1 = new Person("James");

p1.addListener('sayit', function(){
    this.sayMyName("Hello ");
});

p1.emit('sayit');

Connect

"Connect is an extensible HTTP server framework for node using "plugins" known as middleware"

Connect

  • Middleware framework
  • Tasks that needs to be done before request handling
  1. Make our own
  2. Use existing

Connect

Make our own

Connect håller koll på var man är och låter exekveringen löpa kronologiskt genom dina middleware-funktioner

var connect = require('connect');
var server = connect();

var mid1 = function(req, res, next){
    req.gurra = "oyeah!";
    next();
}
var mid2 = function(req, res, next){
    res.end(req.gurra);
}

server.use(mid1);
server.use(mid2);

server.listen(3000);

Mounting

var connect = require('connect');
var colors = require('colors');
var server = connect();

var authcheck = function(req, res, next){
    console.log("Performing difficult auth checks".grey);
    next();
}

var myServer = function(req, res, next){
    console.log("Serving ".green + req.url.green)
    res.writeHead(200);
    res.end("You are at " + req.url);
}

server.use('/admin', authcheck);
server.use(myServer);

server.listen(3000);

Error handling and 404

var connect = require('connect');
var colors = require('colors');
var server = connect();

var mid1 = function(req, res, next){
    if(req.url === "/awesome"){
        console.log("- Success handler: ".grey, "/awesome is awesome".green);
        res.writeHead(200);
        res.end("Wohoo");
    }else{
        next("Something is wrong with req.url: ");
    }
}

var error1 = function(err, req, res, next){
    console.error("- Error handler: ".grey, err.red);
    res.writeHead(404);
    res.end("Nope nothing to see at " + req.url + " (404)");
}

server.use(mid1);
server.use(error1);

server.listen(3000);

Available middleware

body-parser

var connect = require('connect');
var bodyParser = require('body-parser');
var server = connect();

server.use(bodyParser.urlencoded({ extended: false }));

server.use(function(req, res){
    console.log(req.body);

    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(
        "<form method='post'>"+
            "<input name='myText' type='text'/>"+
	    "<input name='myButton' type='submit' />"+
        "</form>");
});

server.listen(3000);

!

Available middleware

querystring

var connect = require('connect');
var querystring = require('qs');
var server = connect();

server.use(function(req, res){
    var query = querystring.parse(req._parsedUrl.query);

    res.writeHead(200, {'Content-Type': 'text/html'});
    res.end(JSON.stringify(query));
});

server.listen(3000);

Express JS

Express is a minimal and flexible node.js web application framework, providing a robust set of features for building single and multi-page, and hybrid web applications.

Express features

  • Routing
  • Template engine
  • REST

Routing

  • REST verbs
  • Separating code layers
var express = require('express');
var router = express.Router();
var app = express();

router.get('/', function(req, res) {
    res.send('index page');
});

router.get('/users', function(req, res) {
    res.send('users page');
});

app.use(router);
app.listen(3000);

Separating code layers

var express = require('express');
var app = express();
var app_routes = require('./route_example_routes');

app.use('/', app_routes);
app.use('/for/fun', app_routes); //same routes reusable

app.use(function(req, res){
    res.status(404).send("Nooope 404!");
});

app.listen(3000);
var router = require('express').Router();


router.get("/users", function(req, res){
    res.send("user listing");
});

module.exports = router;

setup

routes

error handling

setup

route handler

Template engine

h1 Jade - node template engine
  #container.col
    if youAreUsingJade
      p You are amazing
    else
      p Get on it!
<h1>{{ pagename|title }}</h1>
<ul>
{% for author in authors %}
  <li>
    {{ author }}
  </li>
{% endfor %}
</ul>
<ul>
  <% for(var i=0; i<users.length; i++) {%>     
    <li><%= users[i] %></li>
  <% } %>
</ul>
<% if (user) { %>
    <h2><%= user.name %></h2>
<% } %>
<ul>
  <% users.forEach(function(user){ %>
    <p><%= user.name %></p>
  <% }) %>
</ul>
<% include a_template %>

  <!-- lots of other stuff -->

<% include another_template %>

Code!

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

//add 'ejs' to package.json
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

app.use(/* middleware */);

//express app settings
app.set(/* name */, /* value */);
app.get(/* name */);

//route matching
app.get(/*route*/, function(req, res){
  res.render(/*ejs file*/, {'view': 'variables'});
});

app.post(/*route*/, function(req, res){
  res.status(/*http code*/).send(/*content*/);
});

var server = app.listen(3000);

http://expressjs.com/4x/api.html

Rate My Fika!

$ express -e ratemyfika

$ npm install

style.css !

rename 'users' to 'fika'

fikan.json !

$ npm install -g express-generator

Rate My Fika!

render index.ejs with fikan.json

add markup to support fika data

new markup for voting

add route for post /vote

let script capture voting clicks

Next time

  • REST
  • File upload
  • Session handling
  • ...and fikAPI

Node.JS #2

By Gustav Jorlöv

Node.JS #2

  • 823