diff --git a/01 Setup.md b/01 Setup.md index 065039bd..3bd171e2 100644 --- a/01 Setup.md +++ b/01 Setup.md @@ -143,35 +143,32 @@ Now we have the server up and running so the final task is to view the web page ## 5 Using npm and its package.json -**Have a look at your `package.json` file and understand its contents** +**Have a look at your `package.json` file and understand its contents**. - When you are starting a new _project_, **you have to create this yourself**: - 1. Use the `npm init` command to create the package.json file - - You can leave all the options default, just leave them empty and keep pressing enter - - Alternatively you can run `npm init --yes`, it will simply leave everything default - 2. Install the dependencies for the first time using the `-S` _switch_ with `npm install` - - e.g.: `npm install -S koa koa-bodyparser` - - This would add something like this to the `package.json` file: - ```json - "dependencies": { - "koa": "^2.11.0", - "koa-bodyparser": "^4.2.1" - } - ``` - - When you next run `npm install -S `, the given package's _newest version_ will be simply added to the list, or in case of a new version for a _previously listed_ dependency, the _version number_ will be updated - - This `-S` is just a short version of the `--save` _switch_ - - **You can use the alternative `--save-dev` switch to install and save them as _development dependencies_** - - Something that you wouldn't want to deploy, but is necessary for development - - E.g. we will use `jest` for testing, and `eslint` for linting during the development phase, but these shouldn't be required to be installed during deployment - - You are done with adding the dependencies, now simply use `npm install` to install all of them at once! - - If you don't want to install development dependencies, use `npm install --production` - 3. This `package.json` file is also useful to store _scripts_: - - Look at the following line: ` "start": "nodemon index.js"` - - This lets us simply type `npm start` in the terminal to start our application via _nodemon_ - - Nodemon is a great tool that restarts the application every time we save a file in the given folder, so we don't actually have to manually stop and restart it after every modification. - - - +1. Use the `npm init` command to create the package.json file + - You can leave all the options default, just leave them empty and keep pressing enter + - Alternatively you can run `npm init --yes`, it will simply leave everything default +2. Install the dependencies for the first time using the `-S` _switch_ with `npm install` + - e.g.: `npm install -S koa koa-bodyparser` + - This would add something like this to the `package.json` file: + ```json + "dependencies": { + "koa": "^2.11.0", + "koa-bodyparser": "^4.2.1" + } + ``` + - When you next run `npm install -S `, the given package's _newest version_ will be simply added to the list, or in case of a new version for a _previously listed_ dependency, the _version number_ will be updated + - This `-S` is just a short version of the `--save` _switch_ + - **You can use the alternative `--save-dev` switch to install and save them as _development dependencies_** + - Something that you wouldn't want to deploy, but is necessary for development + - E.g. we will use `jest` for testing, and `eslint` for linting during the development phase, but these shouldn't be required to be installed during deployment + - You are done with adding the dependencies, now simply use `npm install` to install all of them at once! + - If you don't want to install development dependencies, use `npm install --production` +3. This `package.json` file is also useful to store _scripts_: + - Look at the following line: ` "start": "nodemon index.js"` + - This lets us simply type `npm start` in the terminal to start our application via _nodemon_ + - Nodemon is a great tool that restarts the application every time we save a file in the given folder, so we don't actually have to manually stop and restart it after every modification. ## 6 Pushing the Changes to GitHub diff --git a/02 HTTP.md b/02 HTTP.md index 39e3792d..d1817184 100644 --- a/02 HTTP.md +++ b/02 HTTP.md @@ -53,7 +53,7 @@ Study the `index.js` script in the `exercises/02_http/01_url/` directory. 3. `koa-bodyparser` 4. `koa-static` 5. `js2xmlparser` - - **You can install all these dependencies by simply running 'npm install' in the terminal.** + - **You can install all these dependencies by simply running `npm install` in the terminal.** - This command installs all the documented dependencies from the `package.json` file, which is already preconfigured in this case. - Refer to the `01_Setup.md` document's `Using npm and its package.json` chapter for more information @@ -66,7 +66,7 @@ Study the `index.js` script in the `exercises/02_http/01_url/` directory. 6. The main part of the script defines the _routes_ and we will be covering these in more detail as we progress through the lab. 7. Right at the end (line 138) we start the server on the defined port and _export_ the _koa object_ `app`. By exporting it we can import the script into our automated test suite (briefly covered in the previous lab). -Now start the server: +Now start the server by typing `npm start` into the terminal while in the correct directory and hitting enter: 1. Access the root url, notice that the message **Hello World** is displayed in the browser. 2. Access the `/anon` url. This should result in the same message being displayed. @@ -74,7 +74,7 @@ Now start the server: ### 1.2 URL Parameters -In the HTTP protocol URLs represent resources on the server. Up to this point each URL has matched a different _route_ (defined by an `router.get()` function) but on a real server there might be a database containing many thousands of records that we want to be able to access. For this to work, each record would need a different, unique, URL! Since each record in an SQL database has a unique key (primary key), a simple solution would be to include the primary key in the URL thus creating a different URL for each record. +In the HTTP protocol URLs represent resources on the server. Up to this point each URL has matched a different _route_ (defined by a `router.get()` function), but on a real server there might be a database containing many thousands of records that we want to be able to access. For this to work, each record would need a different, unique, URL! Since each record in an SQL database has a unique key (primary key), a simple solution would be to include the primary key in the URL thus creating a different URL for each record. To do this we need to extract some data from the http object `ctx` which is the parameter passed to the _anonymous callback function_. The `ctx` object is a _JavaScript Object_ and so we need to fully understand how these work. @@ -117,8 +117,8 @@ Each value in an object can be extracted using one or two different syntaxes: ```javascript const firstName = name.first const lastName = name['last name'] -const prop = year -const dobYear = name.dob.[prop] +const prop = 'year' +const dobYear = name.dob[prop] ``` New properties can be added and removed from an object. @@ -136,11 +136,11 @@ In this section you will learn about a number of JavaScript functions. In each c 1. Add a fourth book to the array and make sure you can access this by passing its index in the URL. 2. We are not restricted to only having two URL segments: 1. Modify the route to add a second parameter called `index2`. - 2. Make sure this is triggered by restarting the server and accessing this by passing a second parameter. + 2. Make sure this is triggered by restarting the server (which should happen automatically if you used `npm start`, which uses `nodemon`) and accessing this by passing a second parameter. 3. Modify the script to print out both book titles. 3. Next you need to add some validation to make sure the script does not crash (note that if you are using GoormIDE you will not be able to test it): 1. If the index in the URL exceeds the number of books in the array, you get an error. Insert an [`if...else` statement](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/if...else) that sends a suitable message to the browser if the index number in the URL is too high. - 2. The index must be a number. Use the [`isNaN()` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN) to check and send a suitable message to the browser if it is not. if it is, use the [`parseFloat()` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat) to convert it to a number. + 2. The index must be a number. Use the [`isNaN()` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN) to check and send a suitable message to the browser if it is not. If it is, use the [`parseFloat()` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat) to convert it to a number. 3. The number needs to be a whole number (integer). All JavaScript numbers are objects and have a number of useful functions. Use the [`Number.isInteger()` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger) to check it is indeed an integer. Send a suitable message to the browser if it is not. You can convert it to an integer using the [`parseInt()` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt). ### 1.3 URL Query Strings @@ -148,7 +148,7 @@ In this section you will learn about a number of JavaScript functions. In each c Whilst URL parameters are used to define unique URLs to identify online resources, sometimes we want to be able to pass additional information and this is done through the use of **query strings**. 1. Restart the server and access the `/hello/John%20Doe` route. - 1. Since spaces are not permitted in a URL we have to replace spaces with special codes. This is known as **URL Encoding** and there are specific [codes](https://www.degraeve.com/reference/urlencoding.php) to use. + 1. Since spaces are not permitted in a URL we have to replace spaces with special codes. This is known as **URL Encoding** and there are specific [codes](https://www.degraeve.com/reference/urlencoding.php) to use; however, your browser will probably do this automatically. 2. Notice that the message `hello John Doe` is displayed in the browser. 2. Now change the URL to `/hello/John%20Doe?format=upper`. 1. Notice that the same data has been displayed just the format has changed. @@ -179,7 +179,7 @@ Headers allow for additional information to be passed: Make sure the server is still running and use the [Chrome web browser](https://www.google.com/chrome/) to access the root URL `/`. -1. Open the [Chrome Developer Tools](https://developers.google.com/web/tools/chrome-devtools/) by clicking on the _Customise and control Chrome_ button (the three dots to the extreme right of the address bar), choosing **More tools** from the menu and then **Developer tools** from the submenu. +1. Open the [Chrome Developer Tools](https://developers.google.com/web/tools/chrome-devtools/) by pressing `ctrl+shift+i` or by clicking on the _Customise and control Chrome_ button (the three dots to the extreme right of the address bar), choosing **More tools** from the menu and then **Developer tools** from the submenu. 2. Locate the **Network** tab in the Chrome developer tools. 3. Reload the web page. (Press F5) 4. You should now see the resource sent in the HTTP response together with some data dealing with response times. @@ -201,7 +201,7 @@ In the **Request Headers** note that: 2. Next it specifies the host the request is being sent to. 3. Then there are multiple request headers. These are always property-value pairs. Lets look at a few of the more interesting ones: 1. The `User-Agent` header sends information about the browser being used. - 2. The `Accepts` header tells the server what [MIME](https://goo.gl/W2SWtZ) data types our browser prefers. + 2. The `Accepts` header tells the server what [MIME data types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) our browser prefers. In addition to the **Response Body** (the information in the web browser window), the server has returned a **Status Code** (in this case it is `200` meaning `OK`) plus a set of **Response Headers** that provide additional information. @@ -215,14 +215,12 @@ As part of the worksheets you will be given some exercises to carry out to make 1. Go to the [University website](http://www.coventry.ac.uk) and use the Chrome Developer Tools to examine the request and response headers. 1. Are there any headers that were missing from the example above? - 2. [Look up](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) the meaning of all the headers. + 2. Look up the meaning of all the [headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers). ## 2 Using the POST Method Now we have a good understanding of the request-response process used by the HTTP protocol and have learned about the headers we will extend this by examining the use of the HTTP POST method. -Before completing this section in the lab sheet you will need to install the `koa-static` package. - 1. Start by accessing the list of names on the `/names` url Make sure you have the Chrome Developer Tools open on the Network tab.: 1. Notice the browser displays an error message. 2. If you look at the HTTP Status Code you will see it is `404 Not Found` which makes sense as there are no names in the list (yet) @@ -231,12 +229,12 @@ Before completing this section in the lab sheet you will need to install the `ko 1. Notice that the Request Method has changed to `POST`. 2. Notice that the Response Code is `201 Created` to indicate that your data has been uploaded and stored. 3. There is a section called **Form Data** which is the request body and contains the data you submitted using the form. Use the _View Source_ link to display the raw data. This is how your data is sent to the server. -4. Use the back button to return to the form and use this to add the names of everyone else on your table. +4. Use the back button to return to the form and use this to add the names of everyone else at your table. 5. Access the `/names` url which should now respond with the HTTP Status Code `200 OK` and display your names in an HTML table. ## 3 Meta-Data -The path in the Uniform Resource Locator (URL) represents a _resource_ on the server however sometimes you need to pass _metadata_ to tell the server what you want it to do with this resource. There are two ways to pass metadata in an HTTP request, query strings and request headers. They differ in that anything in the URL is part of a book mark whilst the request headers are not. You need to decide whether this is important before deciding which to use. +The path in the Uniform Resource Locator (URL) represents a _resource_ on the server; however, sometimes you need to pass _metadata_ to tell the server what you want it to do with this resource. There are two ways to pass metadata in an HTTP request, query strings and request headers. They differ in that anything in the URL is part of a bookmark whilst the request headers are not. You need to decide whether this is important before deciding which to use. ### 3.1 Query Strings @@ -262,7 +260,7 @@ To complete this section of the lab you need to install the [Modify Headers](htt ![editing the request headers](exercises/.images/chrome_05.png) -You can also modify the standard request headers. In this example we will change the `Accept` header which defines the prefered format of the response data. The data formats are defined as [MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types) The default settings look something like: +You can also modify the standard request headers. In this example we will change the `Accept` header which defines the prefered format of the response data. The data formats are defined as [MIME types](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types). The default settings look something like: ``` text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 @@ -271,7 +269,7 @@ text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*; This specified that the browser would prefer data in HTML/XML format (0.9 weighting) but will accept certain image formats and everything else. We will be changing this to request our data in specific formats. 1. Still on the `/names` URL, modify the request headers by removing any search terms. -2. Add a custom `Accept` header which will modify the default and set its value to `text/html` (see the screenshot below). If you refresh the browser you will see that the data is still displayed in an HTML table (because this format has been provided by the server). +2. Add a custom `Accept` header which will modify the default and set its value to `text/html` (see the screenshot below). If you refresh the browser you will see that the data is still displayed in an HTML table (because this format was used previously as well). 3. Now try the following MIME types: 1. `application/json` 2. `application/xml` diff --git a/03 HTML5.md b/03 HTML5.md index ce5419c8..15f2d85f 100644 --- a/03 HTML5.md +++ b/03 HTML5.md @@ -18,7 +18,7 @@ In this worksheet you will be learning about the markup language HTML which is c ## 1 Syntax -Lets take a look at some basic HTML syntax. Start by locating the `exercises/03_html/01_syntax/` directory. Navigate to this using the SSH Terminal, install the all the necessary `koa` packages and start the web server. If you navigate to the base route `/` you will see a screen full of text. +Lets take a look at some basic HTML syntax. Start by locating the `exercises/03_html/01_syntax/` directory. Navigate here using the terminal, install all the necessary `koa` packages with `npm install` and start the web server with `node index.js`. If you navigate to the base route `/`, you will see a screen full of text. ![the unformatted text](exercises/.images/chrome_07.png) @@ -35,7 +35,7 @@ As you work, save the html file and refresh the browser, you don't need to resta ## 2 Lists -Now you have mastered the basics of html its time to move on to how it can be used to render lists of different types. Start by locating the files in the `exercises/02_html/02_lists/` directory. Now install the necessary packages, start the `koa` server and view the root URL `/`. This should display a simple page with the title **1980's Home Computers**. +Now that you have mastered the basics of HTML, it's time to move on to how it can be used to render lists of different types. Start by locating the files in the `exercises/02_html/02_lists/` directory. Now install the necessary packages, start the `koa` server and view the root URL `/`. This should display a simple page with the title **1980s' Home Computers**. Now, add a list on your web page. Insert the following lines of code after the paragraph describing clever uses for home computers: @@ -83,7 +83,7 @@ The definitions list contains two elements for each item: a `dt` for the term an ## 3 Hypermedia -Now you have mastered the basics of HTML markup we will look at one of the most important features, the ability to link resources together (known as **hypermedia**), this is one of the cornerstones of the World Wide Web (WWW). +Now that you have mastered the basics of HTML markup, we will look at one of the most important features, the ability to link resources together (known as **hypermedia**), this is one of the cornerstones of the World Wide Web (WWW). ### 3.1 Routes @@ -91,11 +91,11 @@ Every resource on the WWW (such as html documents and images) has a unique URL a 1. Some resources need to be directly accessible in the web browser (they are accessed either directly or loaded by the html web page). These need to have their own directly accessible URL. 1. One directory needs to be specified as being publicly available. In this example we have created a directory called `public/` - 2. Koa needs to make this directory public. This is achieved on line by importing a static module and using this to specify the public directory. + 2. Koa needs to make this directory public. This is achieved on line 8 by importing a static module and using this to specify the public directory. 3. Assuming the server is running you can directly view the image using the URL `http://localhost:8080/paradox.jpeg`, remembering to substitute your server's URL. 2. Some resources are _virtual_ and are generated by a script running on the server before being sent back to the browser client. 1. There are some simple examples in `index.js`. Both the `/` and `/paradoxes` routes trigger scripts that take the contents of html files and send this back to the browser. - 2. When you access the `/date` route it displays today's date. Look at the script that does this (you don't need to understand the code details). + 2. When you access the `/date` route it, displays today's date. Look at the script that does this (you don't need to understand the code details). #### 3.1.1 Test Your Knowledge @@ -154,7 +154,7 @@ Sinclair ZX Spectrum ### 3.3 Images -In HTML5, images are put inside a `figure` element. The `figure` element normally contains one image, possibly with a caption, but technically it can serve as a container for multiple images. because the images are loaded by the HTML web page (and not directly by the web server) they need to be in a publicly accessible directory. On our web server this has been defined as the `public/` directory. You should create subdirectories within this to organise your files. +In HTML5, images are put inside a `figure` element. The `figure` element normally contains one image, possibly with a caption, but technically it can serve as a container for multiple images. Because the images are loaded by the HTML web page (and not directly by the web server) they need to be in a publicly accessible directory. On our web server this has been defined as the `public/` directory. You should create subdirectories within this to organise your files. Locate the `03_hypermedia/public/` directory and create a new folder inside this called `images/`. Find an image of a 1980s computer and drag it into this new directory. You can use the image below if you wish. @@ -247,12 +247,12 @@ Verify that you understand the elements used in marking up the table: ## 5 Semantic Markup -In this final exercise we will look at how [MicroData](https://developer.mozilla.org/en-US/docs/Web/HTML/Microdata) can be used to add semantic information to a web page. Start by using the SSH Terminal to run the server in the `exercises/03_html/05_semantic/` directory and navigating to the base route `/`. This should display a simple review page. +In this final exercise we will look at how [MicroData](https://developer.mozilla.org/en-US/docs/Web/HTML/Microdata) can be used to add semantic information to a web page. Start by using the terminal to run the server in the `exercises/03_html/05_semantic/` directory and navigating to the base route `/`. This should display a simple review page. 1. Paste the HTML code into Google's [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool) to see what semantic data it contains. Notice: - 1. There are two **items** on in the webpage, a movie and a rating. These are defined using the `itemscope` attribute in the html. Each item has an `itemtype` attribute that points to the appropriate Microdata definition. + 1. There is one main **item** on the webpage, which is a `review`, but it has many properties, some of which also consist of other **items**. These are defined using the `itemscope` attribute in the HTML file. Each item has an `itemtype` attribute that points to the appropriate Microdata definition. 2. Within each `itemscope`, the information has been tagged using the `itemprop` attribute. The allowed values are defined by the `itemtype` definition available on the [Schema.org website](http://schema.org/docs/full.html). - 3. The schema definitions define what `itemtype` are allowed and also what items can be nested inside which items. + 3. The schema definitions define what `itemtype`s are allowed and also what items can be nested inside which items. 2. The [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool) will not only extract the metadata but will also identify any errors in your implementation of the MicroData schema. 3. Install the [Structured Data Testing Tool Plugin](https://chrome.google.com/webstore/detail/structured-data-testing-t/kfdjeigpgagildmolfanniafmplnplpl/related?hl=en) for your Chrome Browser and use it to see the metadata. @@ -267,7 +267,7 @@ Hand-coding HTML can be a hassle, especially because you have to remember to add Start by running the server (note that you need to install an additional package called `marked`). 1. View the root path `/`. Notice that it displays a web page. -2. Use the **Elements** tab in the Chrome Developer Tools to view the markup, notice that the page contains a `

`,a `

` element plus an ordered list and a table. +2. Use the **Elements** tab in the Chrome Developer Tools to view the markup, notice that the page contains an `

`, a `

` element, plus an ordered list and a table. 3. Now open the `computers.md` file: 1. Notice how a single `#` symbol is used to denote a top level `

` element. 2. The `

` paragraph is denoted by text with no additional markup. diff --git a/exercises/02_http/01_url/index.js b/exercises/02_http/01_url/index.js index acf845f0..50e91348 100644 --- a/exercises/02_http/01_url/index.js +++ b/exercises/02_http/01_url/index.js @@ -73,8 +73,8 @@ router.post('/form', ctx => { router.get('/names', ctx => { let list = names - let search = 'x' - const minLength = 3 + let search = '' + const minLength = 1 if(ctx.query.search && ctx.query.search.length >= minLength) { search = ctx.query.search.toLowerCase() diff --git a/solutions/02_http/01_url/index.js b/solutions/02_http/01_url/index.js index e26c5ff1..000cfda9 100644 --- a/solutions/02_http/01_url/index.js +++ b/solutions/02_http/01_url/index.js @@ -67,7 +67,7 @@ router.get('/hello/:name', ctx => { // only applies uppercase if formatting query exists if (ctx.query.format === 'upper') myname = myname.toUpperCase() - if (ctx.query.format === 'upper') myname = myname.toLowerCase() + if (ctx.query.format === 'lower') myname = myname.toLowerCase() if (ctx.query.reverse === 'true') { myname = myname.split('').reverse().join('') @@ -93,8 +93,8 @@ router.post('/form', ctx => { router.get('/names', ctx => { let list = names - let search = 'x' - const minLength = 3 + let search = '' + const minLength = 1 if(ctx.query.search && ctx.query.search.length >= minLength) { search = ctx.query.search.toLowerCase()