WebFund 2016W Lecture 9

From Soma-notes
Jump to navigation Jump to search

Video

The video from the lecture given on February 4, 2016 is now available.

Notes

Agenda

  • We are now a week away from the midterm (February 11th, 2016)
  • The solutions for Assignment 3 will be reviewed in class on Tuesday, February 9th
  • In this class the focus was on extending the functionality of tinyweb.js to that of form-demo.js and examforms.js in lieu of introducing new topics before the midterm

Version Control

  • Question: How many people have used CVS or Github previously? Has version control been covered in previous courses?
    • Majority of class indicated that version control has not been a topic covered in previous courses.
  • Pros of version control:
    • The ability to create backups and branch code
    • Github is a great resource for powerful collaboration, code review, and code management for open source and private projects. Public projects are always free. (https://github.com/ )
  • Git was originally developed for the Linux kernel.
  • Code Academy has a Github tutorial - https://www.codecademy.com/learn/learn-git
  • Diff command was recommended – analyzes two files and prints the lines that different. (diff file1.js file2.js)
    • e.g diff ~/Documents/Class/WebFund/2016W/code tinwebserver.js tinywebserver_solution

tinyweb.js vs form-demo.js

  • They can both serve static files
  • tinyweb.js:
    • tinyweb.js serves static content from the directory specified as the options directory
    • A file on disk is served for a particular URL. As a result, the content always remains the same (static content)
  • form-demo.js:
    • form-demo serves static content form a public directory
    • Can handle form submissions... this depends upon handling dynamic content since the whole point is to change the state of the web server
    • Supports jade templates
    • Can run code to generate pages... meaning that there are functions that are run every time a request is made for a particular URL (dynamic content)
      • e.g in form-demo/routes/index.js:
router.get('/', function(req, res, next) {
   res.render('index', { title: 'COMP 2406 Simple form demo' });
});

Coding Exercise - Adding More Functionality To tinyweb.js

  • To get started, it’s better to initially create data structures and then create code to support the data structures
  • First step of emulating form-demo was to create the framework for the routing functions (‘/’ , ‘/add’, “/list’).
    • Must follow the definition of var route_get..., var route_post... and var_route_list... functions in order to avoid the generation of “Type Error: the Route is not a function error.
// routes is a mapping of the url’s we want to come in and the code we want to run when the url’s are run.
var routes = {
   ‘/’: route_index,
   ‘/add’ : route_add,
   ‘/list’ : route_list
}
  • The following code was copied from index.js:
router.get('/', function(req, res, next) {
   res.render('index', { title: 'COMP 2406 Simple form demo' });
});
 
router.post('/add', function(req, res) {
   var obj = { name: req.body.name,
	       city: req.body.city,
               country: req.body.country,
               birthday: req.body.birthday,
               email: req.body.email };
   state.push(obj);
   res.render('add', { title: 'Person just added', item: obj });
});
 
router.get('/list', function(req, res) {
   res.render('list', { title: 'People Listing',  items: state});
});
  • The above code was pasted into tinyweb-forms.js after var options; and before the definition of the routes object
  • The code was adapted as shown below
    • Note the next argument was removed from functions since this argument is not needed in our version
//The purpose of these functions is to render a template using jade and respond with the rendered HTML
//We will be making modifications to achieve this

//This one has been partially changed and now provides a response with a static web page
var route_index  = function(req, res) {
   //res.render('index', { title: 'COMP 2406 Simple form demo' });
   respond(req, res, 200, “<html><body><h1>Success!</h1></body></html>”,”text/html”); //tiny web page 
}
 
var route_add = (function(req, res) {
   var obj = { name: req.body.name,
	       city: req.body.city,
               country: req.body.country,
               birthday: req.body.birthday,
               email: req.body.email };
   state.push(obj);
   res.render('add', { title: 'Person just added', item: obj });
}
 
var route_list = (function(req, res) {
   res.render('list', { title: 'People Listing',  items: state});
}
  • To get the above functions called, the code to tinyweb_forms.js was modified in the request_handler function just after the following if statement:
if(options.aliases.hasOwnProperty(url)){
   myConsole.log(“Aliasing “ + url + “ to “ + options.aliases[url]);
   url = options.aliases[url];
}
  • The code that was added is:
if (routes.hasOwnProperty(url)) {
   theRoute = routes[url]; // look it up and send the info the return and response
   return theRoute(request, response); // arguments used from var request_handler
}
  • We do not use the serve file function since we are generating content dynamically
  • To make sure the code ran correctly, the tinyweb-options.json, error.html and tinyweb-forms.js files were moved to the same folder
  • Furthermore, the tinyweb-options.json file was modified from
{
   “host”: “localhost”,
   “port”: 8000,
   ”index”: ”index.html”,
   ”docroot” : “.”,
   “logged-headers”: [”user-agent”, “referrer”],
   ”errorpage”: ”error.html”,
   ”aliases”: {
 	”/index.html”: “/hello.html”,
 	“/”: “/hello.html”,
	“/really/cool.html”: “/notcool.html”
   }
}
  • To:
{
   “host”: “localhost”,
   “port”: 8000,
   ”index”: ”index.html”,
   ”docroot” : “.”,
   “logged-headers”: [”user-agent”, “referrer”],
   ”errorpage”: ”error.html”,
   ”aliases”: {
 	”/index.html”: “/”,
 	“/hello.html”: “/”,
	“/really/cool.html”: “/notcool.html”
   }
}
  • In order to render the Jade template, the following line was added at the top of the script:
var jade = require(‘jade’);
  • In order to load Jade in this way, you must run the following command in the folder that contains the tinyweb-forms files:
npm install jade
  • A node_modules sub folder will be created
  • The jade files from form-demo/views(templates) can now be moved over to the tinyweb-forms folder (main folder)
  • The route_index function is then modified as follows to in order to use the Jade template
    • Note that an async function is used to ensure this is done in a non-blocking fashion... we want the webserver to remain responsive for other incoming requests
var route_index  = function(req, res) {
  
   var content, template, options;

   var render_template = function(err, template){
      content = jade.render(template, options);
      respond(req, res, 200, content, ”text/html”); 
   }

   options = {pretty: true,
              title: 'COMP 2406 Tinyweb Forms Demo'};

   return fs.readFile(“index.jade”, ”utf-8”, render_template);
}
  • When the code above was run errors that were generated were:
    • Error #1:
      • Error: Jade:1
      • >1 extends layout….the “filename” option is required to use ”extends” with ””relative” paths... because it doesn’t know what file to load
    • Solution #1: add a reference to index.jade
var route_index = function(req, res) {
  
   var content, template, options;

   var render_template = function(err, template){
      content = jade.render(template, jade_options);
      respond(req, res, 200, content,”text/html”); 
   }

   jade_options = {pretty: true,
                   title: 'COMP 2406 Tinyweb Forms Demo',
                   filename: ‘index.jade’};

   return fs.readFile(jade_options.filename, ”utf-8”, render_template);
}

// The calls to fs.readFile(), jade.render() and respond() are all needed to get the functionality of the res.render() which was contained exam-forms
    • Error #2:
      • A 404 error was generated for style.css
    • Solution #2:
      • Copy the stylesheet over to the form-demo folder
      • Once this was done, prettier fonts were generated and the 404 error was no longer generated
    • Error and Solution #3: Unexpected identifier
      • Generated because there was a comma missing at the end of title: 'COMP 2406 Tinyweb Forms Demo', in the jade_options object
  • Next, we moved on to modifying code to redirect the /add route to /list
var route_add = (function(req, res) {
   // var obj = { name: req.body.name,
   //		  city: req.body.city,
   //             country: req.body.country,
   //             birthday: req.body.birthday,
   //             email: req.body.email };
   //state.push(obj);
   //res.render('add', { title: 'Person just added', item: obj });

   myConsole.log(“302” + “\t” + req.method + “\t”  + req.url);

   res.writeHead(302, {
       “Content-Type”: “text/html”
       “Location”: “/list”
   });
   return res.end();
 
   respond(req, res, 200, content, “text/html”);
}
 
var route_list = (function(req, res) {
   res.render('list', { title: 'People Listing',  items: state});
}
  • By setting the appropriate HTTP response code and response headers, we indicate to the client's browser that it should make another request in order to achieve the redirection
  • In examforms.js, res.redirect(‘/list’); handles this same functionality for redirection

To Summarize

  • The changes that we made in this exercise include:
    • Giving tinyweb the ability to run code to dynamically generate response for incoming requests
    • Bringing in the functionality to render templates and respond with the rendered HTML
    • Implementing redirection in response to some requests
  • The code in this exercise does not:
    • Save the state of the data (the data does not persist after the server is shut down)
    • Store the state object (the people added in the form)
    • Render the contents of the list

Additional Notes

  • Don’t use globals for data unless you are thinking explicitly that the data will be shared
    • e.g the state array used in this code may not be well-suited as a global variable
  • Web servers have databases so that they can persistently store their data (don’t want the data to go away) and concurrently access the data
    • This is a better alternative for storing the state data
  • The code modifications made in this exercise to bridge the gap between tinyweb.js and examforms.js were very specific
    • examforms.js is far more robust in terms of how it’s coded