WebFund 2016W: Assignment 2: Difference between revisions

From Soma-notes
No edit summary
 
(10 intermediate revisions by the same user not shown)
Line 1: Line 1:
'''This assignment is not yet finalized.'''
'''The solutions [http://homeostasis.scs.carleton.ca/~soma/webfund-2016w/code/tinyweb.js are now available].'''


In this assignment you will be be extending the functionality of tinywebserver.js from [[WebFund 2016W: Tutorial 2|Tutorial 2]].  There are ?? points in ?? tasks.  This assignment is due on January 27, 2016.
In this assignment you will be be extending the functionality of tinywebserver.js from [[WebFund 2016W: Tutorial 2|Tutorial 2]].  There are 10 points.  This assignment is due on January 31, 2016 (extended from January 28th).


<!-- Please submit your answers as a single text or PDF file called "<username>-comp2406-assign3.txt" or "<username>-comp2406-assign3.pdf", where username is your MyCarletonOne usernameThe first four lines of this file should be "COMP 2406 Assignment 3", your name, student number, and the date.  You may wish to format answers.txt in [http://en.wikipedia.org/wiki/Markdown Markdown] to improve its appearance.  If you do so, you may convert your text file to PDF using [http://johnmacfarlane.net/pandoc/ pandoc].
Please submit your answers as a single text (javascript) file called "tinyweb.js".  Please cite any sources you used in creating your answer as comments in your code.


'''No other formats will be accepted.'''  Submitting in another format will likely result in your assignment not being graded and you receiving no marks for this assignment.  In particular do not submit an MS Word or OpenOffice file as your answers document!
Your tinyweb.js (a modified version of tinywebserver.js) should have the following functionality:
-->
# [1] Add a new 777 status code if there is a request for any document with the word "lucky" in its URL (path or document name).
 
# [1] Add a command line argument which is the name of a configuration file.  This file should contain the contents of the options object.  Note that tinyweb.js should start up correctly without this option file being specified; in this case it should behave as tinywebserver.js does (with respect to the options, not the lucky return code).
Your modified version of tinywebserver.js should have the following functionality:
# Add a new 777 status code if there is a request for any document with the word "lucky" in its URL (path or document name).
# Add a command line argument which is the name of a configuration file.  This file should contain the contents of the options object.  Note that tinywebserver.js should start up correctly without this option file being specified; in this case it should behave as it did originally.
# In the configuration file add the following properties to the option object that change the behavior of the app as follows (note it should also contain all the options that were already part of the options object):
# In the configuration file add the following properties to the option object that change the behavior of the app as follows (note it should also contain all the options that were already part of the options object):
#* logged-headers: an array of headers (as strings) that should be logged for each incoming request.  If no logged headers are specified, no headers should be logged.
#* [2] logged-headers: an array of headers (as strings) that should be logged for each incoming request.  If no logged headers are specified, no headers should be logged.  Header names should be in all lowercase with words separated by dashes.  Thus "UserAgent" becomes "user-agent".  (This change is because this is the format of header names in request.headers.)  The format should be three spaces, the header name, a colon, a space, then the contents of the header.
#* logfile: the filename where to write log messages.  They should be written to standard out (as console.log does) if no logfile is specified.
#* [2] logfile: the filename where to write log messages.  They should be written to standard out (as console.log does) if no logfile is specified.
#* errorpage: html file to be returned when an error page is returned (not 200).  The 777 status code should NOT return an error page, it should return the regular document (777 is an alias for 200).
#* [2] errorpage: html file to be returned when an error page is returned (not 200).  The 777 status code should NOT return an error page, it should return the regular document (777 is an alias for 200).
#* aliases: object where the key is the alias and the value is what should be substituted.  The alias should be for the entire doc path (the URL without the hostname).
#* [2] aliases: object where the key is the alias and the value is what should be substituted.  The alias should be for the entire doc path (the URL without the hostname).  Aliases should be handled before lucky URL processing (and really, just about everything else).


==Hints==
==Hints==


* To log everything to a file you'll want to use a custom Console object with a special write stream.  To get append-only behavior (as logs shouldn't normally be erased) do something like this:
===log files===
 
To log everything to a file you'll want to use a custom Console object with a special write stream.  To get append-only behavior (as logs shouldn't normally be erased) do something like this:


<source lang="javascript">
<source lang="javascript" line>
// logdemo.js
// invoke as:
//  node logdemo.js <logfile>


    var Console = require('console').Console;
var fs = require("fs");
var Console = require('console').Console;
var logFilename = process.argv[2];
var logStream;


    var logStream = logStream = fs.createWriteStream("log.txt", {'flags': 'a'});
// Note: this doesn't catch all errors, see
// https://www.joyent.com/developers/node/design/errors


     if (!logStream) {
try {
      logStream = process.stdout;
     logStream = fs.createWriteStream(logFilename, {'flags': 'a'});
    }
} catch(e) {
    logStream = process.stdout;
}
 
var myConsole = new Console(logStream);


    var myConsole = new Console(logStream);
myConsole.log("This will be written to a file, unless there was a problem!");
 
    myConsole.log("This will be written to a file, unless there was a problem!");
</source>
</source>


* JSON.parse() is very strict with its parsing, much stricter than regular object declarations in JavaScript.  In particular properties need to be quoted (only with double quotes).  You can use try/catch to allow this to be handled gracefully:
===JSON parsing===
 
JSON.parse() is very strict with its parsing, much stricter than regular object declarations in JavaScript.  In particular properties need to be quoted (only with double quotes).  You can use try/catch to allow this to be handled gracefully:


<source lang="javascript">
<source lang="javascript" line>
     try {
     try {
       options = JSON.parse(fs.readFileSync(optionsFilename, "utf-8"));
       options = JSON.parse(fs.readFileSync(optionsFilename, "utf-8"));
Line 51: Line 61:
     }
     }
</source>
</source>
* Here's as example config file:
 
===example config===
 
Here's as example config file:
 
<source lang="javascript" line>
<source lang="javascript" line>
{
{
Line 58: Line 72:
     "index": "index.html",
     "index": "index.html",
     "docroot": ".",
     "docroot": ".",
     "logged-headers": ["UserAgent", "Referer"],
     "logged-headers": ["user-agent", "referer"],
     "logfile": "tinyweb.log",
     "logfile": "tinyweb.log",
     "errorpage": "error.html",
     "errorpage": "error.html",
     "aliases": {
     "aliases": {
        "index.html": "hello.html",
"/index.html": "/hello.html",
        "/really/cool.html": "notcool.html"
"/": "/hello.html",
"/really/cool.html": "/notcool.html"
     }
     }
}
}
</source>
</source>
===example header log===
Here's an example of the header log messages:
<pre>
404 POST /useName
  user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36
  referer: http://localhost:8000/formtest.html
</pre>

Latest revision as of 19:38, 2 February 2016

The solutions are now available.

In this assignment you will be be extending the functionality of tinywebserver.js from Tutorial 2. There are 10 points. This assignment is due on January 31, 2016 (extended from January 28th).

Please submit your answers as a single text (javascript) file called "tinyweb.js". Please cite any sources you used in creating your answer as comments in your code.

Your tinyweb.js (a modified version of tinywebserver.js) should have the following functionality:

  1. [1] Add a new 777 status code if there is a request for any document with the word "lucky" in its URL (path or document name).
  2. [1] Add a command line argument which is the name of a configuration file. This file should contain the contents of the options object. Note that tinyweb.js should start up correctly without this option file being specified; in this case it should behave as tinywebserver.js does (with respect to the options, not the lucky return code).
  3. In the configuration file add the following properties to the option object that change the behavior of the app as follows (note it should also contain all the options that were already part of the options object):
    • [2] logged-headers: an array of headers (as strings) that should be logged for each incoming request. If no logged headers are specified, no headers should be logged. Header names should be in all lowercase with words separated by dashes. Thus "UserAgent" becomes "user-agent". (This change is because this is the format of header names in request.headers.) The format should be three spaces, the header name, a colon, a space, then the contents of the header.
    • [2] logfile: the filename where to write log messages. They should be written to standard out (as console.log does) if no logfile is specified.
    • [2] errorpage: html file to be returned when an error page is returned (not 200). The 777 status code should NOT return an error page, it should return the regular document (777 is an alias for 200).
    • [2] aliases: object where the key is the alias and the value is what should be substituted. The alias should be for the entire doc path (the URL without the hostname). Aliases should be handled before lucky URL processing (and really, just about everything else).

Hints

log files

To log everything to a file you'll want to use a custom Console object with a special write stream. To get append-only behavior (as logs shouldn't normally be erased) do something like this:

// logdemo.js
// invoke as:
//   node logdemo.js <logfile>

var fs = require("fs");
var Console = require('console').Console;
var logFilename = process.argv[2];
var logStream;

// Note: this doesn't catch all errors, see
// https://www.joyent.com/developers/node/design/errors

try {
    logStream = fs.createWriteStream(logFilename, {'flags': 'a'});	
} catch(e) {
    logStream = process.stdout;
}

var myConsole = new Console(logStream);

myConsole.log("This will be written to a file, unless there was a problem!");

JSON parsing

JSON.parse() is very strict with its parsing, much stricter than regular object declarations in JavaScript. In particular properties need to be quoted (only with double quotes). You can use try/catch to allow this to be handled gracefully:

    try {
      options = JSON.parse(fs.readFileSync(optionsFilename, "utf-8"));
    } catch (e) {
      if (optionsFilename) {
	console.error("Error reading/parsing options file " + optionsFilename +
		    ", using defaults.");
      } else {
	console.log("No options file specified, using defaults.");
      }
      options = default_options;
    }

example config

Here's as example config file:

{
    "host": "localhost",
    "port": 8000,
    "index": "index.html",
    "docroot": ".",
    "logged-headers": ["user-agent", "referer"],
    "logfile": "tinyweb.log",
    "errorpage": "error.html",
    "aliases": {
	"/index.html": "/hello.html",
	"/": "/hello.html",
	"/really/cool.html": "/notcool.html"
    }
}

example header log

Here's an example of the header log messages:

404	POST	/useName
   user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.82 Safari/537.36
   referer: http://localhost:8000/formtest.html