Webserver Programming II

Info 253A: Frontend Web Architecture
Kay Ashaolu

What have we done

  • We have created a server that can accept HTTP requests, and send HTTP responses back
  • We have full control over what we send back as a response
  • We are using JavaScript in order to fully control the back-end

More about routes

  • Routes connect URL paths to callback functions
  • You are essentially creating an "event listener"
    • On the event that a client goes to the "/" path
    • Execute the assigned callback function

Quick note

  • A server application is continuously running
  • It does this so that it always listens to requests
  • In order to exit a NodeJS application you must kill the application
  • This is done in Unix by the keyboard combination
    Control + C

Route Example

app.js

var express = require('express'); // Adding the express library 
var app = express(); // Initializing application

app.get('/', function (req, res) {
  res.send("<html><head><title>Homepage</title></head>\
    <body><h1>This is the home page!</h1></body></html>");
});
app.get('/about', function(req,res) {
  res.send("<html><head><title>About</title></head>\
    <body><h1>This is the about us page!</h1></body></html>")
});
app.get('/blog/post-1', function(req,res) {
  res.send("<html><head><title>Blog 1</title></head>\
    <body><h1>This is the first blog post</h1></body></html>")
});

var server = app.listen(3000, function () {
  console.log('Server on localhost listening on port 3000');
});

What's happening

  • We have explicitly told our server to respond to three GET requests in a specific way
  • We use res.send() to send the raw text that we want our client (the browser) to receive
  • Note that we are sending pure html text to the client. The browser then creates a DOM from that text and displays the web page

What about our static files?

  • Remember our apache server last week, that served CSS and JS files
  • We would need something like that in order to host our own CSS and JS files
  • Otherwise we would need to write our CSS in the app.js file itself

Express and static files

  • Express has a mechanism to set a directory to be treated as a static server
  • When a user goes to a particular path, the file that is there is sent to the client as is
    • Advantage: no code needs to be executed: just send data from the file to client
    • Advantage: this can be cached: only if the file changes does this route's cache needs to be udpated
  • This is different with the routes that we have been using so far

Static example

app.js

var express = require('express'); // Adding the express library 
var app = express(); // Initializing application

// Set the path "/static" to serve files from the static folder
app.use('/static', express.static(__dirname + '/static')); 

// Define your routes here
app.get('/', function (req, res) {
  res.send("<html><head><title>Homepage</title>\
    <link rel='stylesheet' href='/static/css/style.css' /></head>\
    <body><h1>This is the home page!</h1>\
    <script type='text/javascript' src='/static/js/script.js'></script></body></html>");
});

// Start up server on port 3000 on host localhost
var server = app.listen(3000, function () {
  console.log('Server on localhost listening on port 3000');
});

Static example

static/css/style.css

h1 {
	color: blue;
}

Static example

static/js/script.js

alert("script.js has been loaded!");

What's happening here?

  • We have set the path '/static' to run as a static server
  • Any path that starts with '/static' will serve files "as is" from the "static" folder
  • Check it out by going to http://localhost:3000/static/css/style.css

What's happening here?

  • Because of our static server, we can serve our own static files
  • Look at the HTML being sent from the '/' route
  • The HTML code includes a link to a style sheet and an include to a JavaScript file
  • This is why the heading was blue and the alert box appeared

This is great, but...

  • Writing out all of that text within a callback gets annoying quickly
  • What if you want to have HTML code common to several pages on your website?

Templates and template engines

  • There are a myriad of template engines out there
  • The idea is to write the HTML code that does not change in a "template"
  • And then designate placeholders for parts of the web page that does not stay the same
  • This is how dynamic pages are created (more on this next week)

Template Example

  • First we need to install a module that will add this functionality for us
  • Let's add mustache-express, which is a module that integrates express with the mustache template engine
  • We do this by going to the terminal and within the root directory of our project and executing the command:
    npm install mustache-express --save

Template Example

app.js

var express = require('express'); // Adding the express library 
var mustacheExpress = require('mustache-express'); // Adding mustache template system
var app = express(); // initializing application
var template_engine = mustacheExpress(); // initializing template engine

// set the path "/static" to serve files from the static folder
app.use('/static', express.static(__dirname + '/static')); 

// Set templating engine and location of templates
app.engine('html', template_engine); // set html parsing to the template engine
app.set('views', __dirname + '/views');

// Define your routes here
app.get('/', function (req, res) {
  res.render('index.html');
});

// Start up server on port 3000 on host localhost
var server = app.listen(3000, function () {
  console.log('Server on localhost listening on port 3000');
});

Template Example

views/index.html

<html>
	<head>
		<title>Homepage</title>
    	<link rel='stylesheet' href='/static/css/style.css' />
    </head>
    <body>
    	<h1>This is the home page!</h1>
    	<script type='text/javascript' src='/static/js/script.js'></script>
    </body>
</html>

What's happening?

  • This code does the same thing as the previous example
  • However, we loaded the html template "index.html" in the views folder
  • We set the 'views' folder as the location of all templates
  • We set 'html' as an extension of the rendering engine set by the mustache express module
  • That's why when we use "res.render('index.html'), NodeJS knows to go to the views folder and use the mustache-express template rendering engine to render index.html

But why use template engines at all?

  • We ran "index.html" through a template engine
  • But all we did is print the contents of "views/index.html" to the screen
  • Couldn't we do this with static pages?
  • Why use a template rendering engine at all?

Dynamic Pages

  • We want to create pages that are different dependent on many different factors:
    • Authentication
    • Authorization
    • Data embedded in the URI
    • Data submitted in a form
    • Location
    • And so on
  • More on this next week, but here's a sneak peak

Grand Example

app.js (1/3)

var express = require('express'); // Adding the express library 
var mustacheExpress = require('mustache-express'); // Adding mustache template system
var app = express(); // initializing application
var template_engine = mustacheExpress(); // initializing template engine

// set the path "/static" to serve files from the static folder
app.use('/static', express.static(__dirname + '/static')); 

// Set template engine and location of templates
app.engine('html', template_engine); // set html parsing to the template engine
app.set('views', __dirname + '/views');

Grand Example

app.js (2/3)

					 
// An object that contains a quote that we want to display for a day of the week
var quote_db = {
  'sunday': "Life is about making an impact, not making an income. \
  –Kevin Kruse",
  'monday': "Whatever the mind of man can conceive and believe, it can achieve. \
  –Napoleon Hill",
  'tuesday': "Strive not to be a success, but rather to be of value. \
  –Albert Einstein",
  'wednesday': "You miss 100% of the shots you don’t take. \
  –Wayne Gretzky",
  'thursday': "Every strike brings me closer to the next home run. \
  –Babe Ruth",
  'friday': "We become what we think about. \
  –Earl Nightingale",
  'saturday': "Life is what happens to you while you’re busy making other plans. \
  –John Lennon",
}

Grand Example

app.js (3/3)

// Define your routes here
app.get('/', function (req, res) {
  day = req.query.day_of_week;
  console.log("Received request for quote for day " + day);
  res.render('index.html', { 'day': day, 'quote': quote_db[day] } );
});

// Start up server on port 3000 on host localhost
var server = app.listen(3000, function () {
  console.log('Server on localhost listening on port 3000');
});

Grand Example

views/index.html

<html>
	<head>
		<title>Homepage</title>
    	<link rel='stylesheet' href='/static/css/style.css' />
    </head>
    <body>
    	<h1>This is the home page!</h1>

    	<p>The quote for {{day}} is: {{quote}}</p>
    	<br />
          <form action="/" method="GET">
    		<label for="day_select">Select a day</label>
    		<select name="day_of_week" id="day_select">
    			<option value="sunday">Sunday</option>
    			<option value="monday">Monday</option>
    			<option value="tuesday">Tuesday</option>
    			<option value="wednesday">Wednesday</option>
    			<option value="thursday">Thursday</option>
    			<option value="friday">Friday</option>
    			<option value="saturday">Saturday</option>
    		</select>
    		<input type="submit" value="Give me a quote" />
    	</form>
    </body>
</html>

What's happening

  • First we created a form that is going to send an GET request to the "/" route
  • It will pass a parameter called "day_of_week"
  • The server will gain access to that parameter using the req.query object

What's happening

  • The server then accesses its "quote_db" to retrieve a quote for that particular day of the week
  • It then passes the day and the quote to the template engine
  • The template "index.html" replaces the tags {{day}} and {{quote}} with the values specified in the object passed by the function call res.render()
  • And we see it on the screen

Questions?