Commit b03e88cd authored by Nathan Bean's avatar Nathan Bean
Browse files

Changes...

parent 698c4493
......@@ -27,7 +27,7 @@ Let's return to the example of the calcuator. In the moments between your typin
Like batch processing, time-sharing is still used in computing today. If you've used the thin clients in the DUE 1114 lab, these are the current-day equivalents of those early terminals. They're basically a video card, monitor, and input device that are hooked up to a server that runs multiple VMs (virtual machines), one for each client, and switches between them constantly updating each.
### Multitasking
The [microcomputer revolution](https://en.wikipedia.org/wiki/Microcomputer) did not do away with concept. Rather, modern operating systems still use the basic concept of the approach, though in the context of a single computer it is known as [multitasking](https://en.wikipedia.org/wiki/Computer_multitasking). When you write a paper now, your operating system is switching between processes in much the same way that time-sharing switched between users. It will switch to your text editor, processing your last keystroke and updating the text on screen. Then it will shift to your music player and stream the next few thousand bytes of the song you're listening to the sound card. Then it will switch to your email program which checks the email server and it will start to notify you that a new email has come in. Then it will switch back to your text editor.
The [microcomputer revolution](https://en.wikipedia.org/wiki/Microcomputer) did not do away with concept. Rather, modern operating systems still use the basic concept of the approach, though in the context of a single computer it is known as [multitasking](https://en.wikipedia.org/wiki/Computer_multitasking). When you write a paper now, your operating system is switching between processes in much the same way that time-sharing switched between users. It w4ill switch to your text editor, processing your last keystroke and updating the text on screen. Then it will shift to your music player and stream the next few thousand bytes of the song you're listening to the sound card. Then it will switch to your email program which checks the email server and it will start to notify you that a new email has come in. Then it will switch back to your text editor.
The thin clients in DUE 1114 (as well as the remote desktops) are therefore both time-sharing between VMs and multitasking within VMs.
......
......@@ -5,7 +5,7 @@ weight: 70
date: 2018-08-24T10:53:26-05:00
---
Most Node packages are made available as [git](https://git-scm.com) repositories, and _npm_ has built-in support for using git.
Most Node packages are made available as [git](https://git-scm.com) repositories, and npm has built-in support for using git.
## The Repository Property
In your _package.json_ file, you can specify a `"repository"` property, which specifies where the repository for this project exists. Consider the following example of the npm command-line interface package:
......
Node actually defines multiple log functions corresponding to different _log levels_, indicating the importance of the message. These are (in order of severity, least to most):
1. `console.debug()`
2. `console.info()`
3. `console.warn()`
4. `console.error()`
These are all aliases for `console.log()` (`console.debug()` and `console.info()`) or `console.error()` (`console.warn()` and `console.error()`). They don't really do anything different, which might lead you to wonder why they exist...
But remember, JavaScript is a _dynamic_ language, so we can re-define the `console` object with our own custom implementation that _does_ do something unique with these various versions. But because they exist, they can _also_ be used with the built-in console. This way our code can be compatible with both approaches!
\ No newline at end of file
......@@ -7,6 +7,6 @@ date: 2018-08-24T10:53:26-05:00
The first web servers were developed to fulfill a simple role - they responded to requests for HTML documents that were (hopefully) located in their physical storage by streaming the contents of those documents to the client.
![Request-Response Pattern](.guides/img/request-response-pattern.png)
![Request-Response Pattern]({{<static "images/5.0.1.png">}})
This is embodied in our request-response pattern. The client requests a resource (such as a HTML document), and receives either a status 200 response (containing the document), or an error status code explaining why it couldn't be retrieved.
\ No newline at end of file
......@@ -5,7 +5,11 @@ weight: 30
date: 2018-08-24T10:53:26-05:00
---
An important aspect to recognize about how Node's http library operates is that _all_ requests to the server are passed to the request handler function. Thus, you need to determine what to do with the incoming request as part of that function. You will most likely use the information contained within the `http.IncomingMessage` object supplied as the first parameter to your request handler. We often use the name `req` for this parameter, short for _request_, as it represents the incoming HTTP request.
An important aspect to recognize about how Node's http library operates is that _all_ requests to the server are passed to the request handler function. Thus, you need to determine what to do with the incoming request as part of that function.
## Working with the Request Object
You will most likely use the information contained within the `http.IncomingMessage` object supplied as the first parameter to your request handler. We often use the name `req` for this parameter, short for _request_, as it represents the incoming HTTP request.
Some of its properties we might use:
......@@ -30,7 +34,7 @@ function handleRequest(req, res) {
// TODO: Serve the css file
break;
case "/site.js":
// TODO: Serve teh js file
// TODO: Serve the js file
break;
default:
// TODO: Serve a 404 Not Found response
......@@ -45,3 +49,65 @@ Notice that at each branching point of our control flow, we serve some kind of r
![handleRequest() flowchart]({{<static "images/5.3.1.png">}})
## Working with the Response Object
The second half of responding to requests is putting together the response. You will use the `http.ServerResponse` object to assemble and send the response. This response consists of a [status code and message]({{<ref "02-http/09-status-codes">}}), [response headers]({{<ref "02-http/10-response-headers">}}), and a [body]({{<ref "02-http/11-response-body">}}) which could be text, binary data, or nothing.
There are a number of properties and methods defined in the `http.ServerResponse` to help with this, including:
* [ServerResponse.statusCode](https://nodejs.org/api/http.html#http_response_statuscode) can be used to manually set the status code
* [ServerResponse.statusMessage](https://nodejs.org/api/http.html#http_response_statusmessage) can be used to manually set the status message. If the code is set but not the message, the default message for the code is used.
* [ServerResponse.setHeader()](https://nodejs.org/api/http.html#http_response_setheader_name_value) adds a header with the supplied name and value (the first and second parameters)
* [ServerResponse.end()](https://nodejs.org/api/http.html#http_response_end_data_encoding_callback) sends the request using the curently set status and headers. Takes an optional parameter which is the response body; if this parameter is supplied, an optional second parameter specifying the encoding can also be used. A final optional callback can be supplied that is called when sending the stream is complete.
Consider the **501 Not Implemented** response in our example above. We need to send the 501 status code, but there is no need for a body or addtional headers. We could use the `req.statusCode` property to set the property, and the `req.end()` method to send it:
```js
// TODO: Serve a 501 Not Implemented response
res.status = 501;
res.end();
```
The sending of a response with a body is a bit more involved. For example, to send the _index.html_ file, we would need to retrieve it from the hard drive and send it as the body of a request. But as the default status code is 200, we don't need to specify it. However, it is a good idea to specify the `Content-Type` header with the appropriate mime-type, and then we can use the `res.end()` method with the file body once we've loaded it, i.e.:
```js
// TODO: Serve the index page
fs.readFile('index.html', (err, body) => {
if(err) {
res.status = 500;
res.end();
return;
}
res.setHeader("Content-Type", "text/html");
res.setHeader("Content-Length", body.length);
res.end(body, "utf8");
});
```
Notice too, that we need to account for the possibility of an error while loading the file _index.html_. If this happens, we send a **500 Server Error** status code indicating that something went wrong, and it happend on _our_ end, not because of a problem in the way the client formatted the request. Notice too that we use a `return` to prevent executing the rest of our code.
We also supply the length of the response body, which will be the same as the buffer length or the length of a string sent as the body. Binary data for the web is counted in octects (eight bits) which conveniently is also how Node buffers are sized and the size of a JavaScript character.
## Chaining writeHead() and end()
The `http.ServerResponse` object also has a method `writeHead()` which combines the writing of status code, message, and headers into a single step, and returns the modified object so its `end()` method can be chained. In this way, you can write the entire sending of a response on a single line. The parameters to `response.writeHead()` are the status code, an optional status message, and an optional JavaScript object representing the headers, using the keys as the header names and values as values.
Serving the css file using this approach would look like:
```js
// TODO: Serve the site css file
fs.readFile('site.css', (err, body) => {
if(err) return res.writeHead(500).end();
res.writeHead(200, {
"Content-Type": "text/html",
"Content-Length": body.length
}).end(body, "utf8");
});
```
You can use any combination of these approaches to send responses.
{{% notice warning %}}
Some important considerations:
* Be aware that you can only send _one_ reponse per request. Once a response is sent, the connection to the client is effectively closed. Thus, once `resonse.end()` has been invoked, it will log an error if it is attempted again.
* The `response.writeHead()` method actually streams the head to the client. Thus, you cannot run `response.setHeader()` or set `response.statusCode` or `response.statusMessage` after it has been set.
* Similarly, any change to the response object after `response.end()` has been invoked will log an error, as you cannot change the response once it's sent.
{{% /notice %}}
\ No newline at end of file
---
title: "Index Pages"
pre: "6. "
weight: 60
date: 2018-08-24T10:53:26-05:00
---
The original purpose of the World-Wide-Web was to share webpages and other digital resources across the Internet. In many ways, an early web server was like a hard drive that was open to the world. Think about the HTTP methods, `"GET"` is like a file read, `"POST"` is like a write, `"PUT"` and `"PATCH"` like a file modification, and `"DELETE"` was a file erasure.
So, just like when you browse your hard drive using Windows Explorer or other software, it was necessary for these early web pages to display an _index_ - a listing of all the contents of a directory. You've seen similar in Codio if you ever used the "Project Index" option in the run menu - it displays an index of the project directory:
![Codio Project Index Page]({{<static "images/5.6.1.png">}})
This is a pretty standard auto-generated directory listing - it provides the path to the directory being displayed, and all the contents of the directory as hyperlinks. Clicking on a file will open or download it, and clicking a directory will open _that_ directory's auto-generated directory listing.
As the use of the web expanded into commercial and public life, many web developers wanted to replace auto-generated directory listing pages with a carefully designed home page. But auto-generated directory listing pages remained an important feature for many sites that served as a more traditional file server.
The compromise adopted by most web servers was that if the directory contained an HTML file named _index.html_ (or sometimes _index_ with any extension, i.e. _index.php_), that page would be served in leu of an auto-generated index page. Most also allow disabling the directory listing as a configuration option.
{{% notice info %}}
You might be wondering about security if a web server starts exposing directory structure and files willy-nilly. Most web servers will _only_ serve files in a specific directory (often called the _root_ directory) and its subdirectories. In a typical configuration, this root directory is named _public_ or *public_html* to reinforce the idea that it is available to anyone browsing the web.
Files that need to have access restricted to certain people should not be placed in this directory, but be placed behind an authentication mechanism (sometimes referred to as an _auth wall_ or _pay wall_ for subscription-based sites). We'll talk about this more in our chapter on authentication.
{{% /notice %}}
\ No newline at end of file
---
title: "Partial Downloads"
pre: "7. "
weight: 70
date: 2018-08-24T10:53:26-05:00
---
While we normally think of downloading an entire file from the web, there are some situations where it makes sense to download only _part_ of a file. One case is with a large file download that gets interrupted - it makes a lot of sense to start downloading the remaining bytes from where you left off, rather han starting over again. A second case is when you are streaming media; often the user may not watch or listen to the entire media file, so why download the bytes they don't need? Or if it is a live stream, we explicitly _can't_ download the entire thing, becuase later parts do not yet exist!
## Range Headers
HTTP explicitly supports requesting only a part of a resource with the [Range](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range) header. This allows us to specify the unit of measure (typically bytes), a starting point, and an optional end. This header is structured:
```
Range: <unit>=<range-start>-<range-end>
```
Where `<unit>` is the unit of measure, the `<range-start>` is the start of the range to send, measured in the provided unit, and `<range-end>` is the end of the range to send.
Thus, a real-world Range header might look like:
```
Range: bytes=200-300
```
You can also specify only the starting point (useful for resuming downloads):
```
Range: <unit>=<range-start>-
```
Finally, you can specify multiple ranges separated by commas:
```
Range: <unit>=<range1-start>-<range1-end>, <range2-start>-<range2-end>, <range3-start>-
```
Of course, as with all request headers, this indicates a desire by the web client. It is up to the web server to determine if it will be honored.
### Partial Content
Which brings us to the **206 Partial Content** response status code. If the server chooses to honor a range specified in the request header, it should respond with this status code, and the body of the response should be just the bytes requested.
In addition, the response [Content-Range](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Range) header should be included with the response, specifying the actual range of bytes returned. This is similar to the Range header, but includes a the total size:
```
Content-Range: <unit> <range-start>-<range-end>/<size>
```
An asterisk (`*`) can be used for an unknown size.
Also, the [Content-Type]() header should also be included, and match the type of file being streamed.
If _multiple_ ranges are included in the response, the Content-Type is `"multipart/byteranges"` and the response body is formatted similarly to multipart form data.
\ No newline at end of file
---
title: "Introduction"
pre: "1. "
weight: 10
date: 2018-08-24T10:53:26-05:00
---
While the first generation of webservers was used to serve static content (i.e. files), it was not long before developers began to realize that a lot more potential existed in the technologies of the web. A key realization here is that the resources served by the web server _don't need to exist_ to be served.
Consider the directory listing from the previous chapter. It is _not_ based on an existing file, but rather is _dynamically created_ when requested by querying the file system of the server. This brings one clear benefit - if we add files to the directory, the next time we request the listing they will be included.
![Request-Response Pattern]({{<static "images/6.1.1.png">}})
Thus, we can create resources _dynamically_ in response to a request. This is the core concept of a _dynamic web server_, which really means any kind of web server that generates at least some of its content dynamically. In this chapter, we will explore this class of web server.
\ No newline at end of file
---
title: "CGI Scripts"
pre: "2. "
weight: 20
date: 2018-08-24T10:53:26-05:00
---
Before we dig too deeply into dynamic web servers, we should reveiw our technologies used in the web. On the client side, we have HTML, CSS, and JavaScript. Managing communication between the client and server, we have HTTP. But on the server side of the equation, what standard web technologies do we use?
![The Web Technologies]({{<static "images/5.2.1.png">}})
The answer is _none_. There **is no standard server development language**. In fact, web servers can be written in _almost every programming language_. This gives web application developers a tremendous amount of flexibility. Of course, that also means the choice of server-side technologies can quickly become overwhelming.
One technology that emerged to help manage some of this complexity was the [Common Gateway Interface (CGI)](https://en.wikipedia.org/wiki/Common_Gateway_Interface), a web standard that allowed a traditonal static webserver to respond to some requests by running a command-line program and piping the output to the requesting client. The CGI standard defined what variables needed to be collected by the web server and how they would be provided to the script.
The script itself could be written in any language that could communicate using stdin and stdout, though in practice most CGI scripts were written using Perl or Bashscript. This strategy was popular with the system admins responsible for deploying webservers like Apache, as these scripting languages and command-line programs were familiar tools. While CGI scripts can be used to build dynamic web pages, by far thier most common use was to consume forms filled out by a user, often saving the results to a file or database or sending them via email.
CGI scripts are still used today, but they do have some important limitations. First, for each kind of request that needed handled, a new script would need to be written. The open-ended nature of CGI scripts meant that over time a web application becaome a patchwork of programs developed by different developers, often using different languages and organizational strategies. And since running a CGI script typically means starting a separate OS process _for each request_, the CGI approach does not scale well to web applications in high demand.
Thus, web developers began seeking new strategies for building cohesive web servers to provide rich dynamic experiences.
{{% notice info %}}
Your personal web space on the CS Departmental Server supports CGI scripts. So if you would like to try to develop one, you can deploy it there. More details can be found on the support [Personal Web Pages](https://support.cs.ksu.edu/CISDocs/wiki/Personal_Web_Pages#Dynamic_Content) entry.
{{% /notice %}}
\ No newline at end of file
---
title: "Server Pages"
pre: "3. "
weight: 30
date: 2018-08-24T10:53:26-05:00
---
The CGI scripting approach eventually evolved into a concept known as server pages and embodied in the technologies of PHP and Microsoft’s Active Server Pages (ASP), as well as Java Server Pages, and many other less-well-known technologies. While each of these use different scripting languages, the basic idea is the same: Take a traditional static webserver functionality, and couple it with a script interpreter. When most files are requested from the server, the file is served using the same techniques we used in the last chapter. But when a script file understood by our augmented server is requested, the script file is executed, and its output is sent as the response.
This may sound a lot like the CGI Scripts we discussed before, and it certainly is, except for two major innovations. The first of these was that the same interpreter, and therefore OS process, could be used for all requests. As server hardware adopted multiple CPUs and multicore CPUs, additional interpreter processes were added, allowing incoming requests to be responded to concurrently on separate processors.
### Embedded Scripts
The second big innovation innovation was the idea of embedding script _directly in HTML code_. When the server page is interpreted, the embedded scripts would execute, and their output would be concatenated directly into the HTML that was being served.
For example, a PHP page might look like this:
```php
<!DOCTYPE html>
<html>
<head><title>PHP Example</title></head>
<body>
<h1>A PHP Example</h1>
<? php
echo date('D, d M Y H:i:s');
?>
</body>
</html>
```
Notice everything except the `<? php ... ?>` is perfectly standard HTML. But when served by an [Apache server](https://httpd.apache.org/) with [mod_php](https://cwiki.apache.org/confluence/display/HTTPD/php) installed, the code within `<? php ... ?>` would be executed, and its output concatenated into the HTML that would then be served (the `echo` function prints output, and `date()` creates the current time in the specified format).
Similarly, an ASP page doing the same task would look like:
```html
<!DOCTYPE html>
<html>
<head><title>ASP Example</title></head>
<body>
<h1>An ASP Example</h1>
<%
Response.Write Now()
%>
</body>
</html>
```
These files would typically be saved with a special extension that the server would recognize, i.e. _.php_ for PHP files, and _.asp_ for ASP files. Allowing scripts to be directly embedded within HTML made web development with these tools far faster, and as IDEs were adapted to support syntax highlighting, code completion, and other assistive features with these file types also helped prevent syntax errors in both the HTML and script code.
Active Server Pages and PHP remain commonly used technologies today, and a large portion of legacy websites built using them are still in service. In fact, your personal web space on the CS department server is running in an Apache server set up to interpret php files - you could add a php script like the one above and and it would execute when you visited the page. You can visit the support [Personal Web Pages](https://support.cs.ksu.edu/CISDocs/wiki/Personal_Web_Pages#Dynamic_Content) entry for details on doing so.
---
title: "Full Stack Development"
pre: "4. "
weight: 40
date: 2018-08-24T10:53:26-05:00
---
Server pages represented one approach to tackling the dynamic web server challenge, and one that was especially suitable for those web developers who primarily worked with static HTML, CSS, and JavaScript backgrounds. But for those that were already programmers, the server page approach could feel confining. Instead, these programmers wanted more control over the web server and its working parts.
Of course, writing a brand-new web server from the ground up is an exhausting and expensive proposition. So most developers adopted existing technologies that were highly optimized to play a specific role, and wrote server code that would utilize them while adding the dynamic portions.
For a dynamic web server, we can separate the needed functionality into three primary areas:
1. Serving static content
2. Creating and serving dynamic content
3. Providing persistent data storage
## Serving Static Content
We've already discussed file servers extensively, and even discussed some options for optimizing thier performance - like caching the most frequently requested files. There are a number of software packages that have been developed and optimized for this task. Some of the best known are:
* [The Apache HTTP Server Project](https://httpd.apache.org/), an open-source server project originally launched in 1995, and consistently the most popular server software on the Internet. The CS department website is hosted on an Apache server, as is your personal web site on the deparmental server.
* [Internet Information Services (IIS)](https://www.iis.net/), Microsoft's flagship web server bundled with the Windows Server operating system.
* [Nginx](https://www.nginx.com/) is also open-source, and intended to be a lighter-weight alternative to Apache HTTP.
## Creating and Serving Dynamic Content
Creating and serving dynamic content is typically done by writing a custom application. As pointed out above, this can be done using any programming language. The strategies employed in such web server designs depend greatly upon the choice of language - for example, Node webservers rely heavily on asynchronous operation.
Some interpreted programming langauges are typically managed by a web server like Apache, which utilizes plug-ins to run [PHP](https://cwiki.apache.org/confluence/display/HTTPD/PHP), [Ruby](https://www.modruby.net/), or [Python](http://modpython.org/). Similarly, IIS runs ASP.NET program scripts written in C# or Visual Basic. This helps offset some of the time penalty incurred by creating the dynamic content with an interpreted programming language, as static content benefits from the server optimizations.
In contrast, other languages are more commonly used to write a web server that handles _both_ static and dynamic content. This includes more system-oriented languages like [C/C++](https://isocpp.org/), [Java](https://www.java.com/), and [Go](https://golang.org/)and more interpreted languages like [Node.js](https://nodejs.org/).
## Providing Persistent Data Storage
While a file system is the traditional route for persistent storage of data in files, as we saw in our discussion of static file servers, holding data in memory can vastly improve server performance. However, memory is _volitale_ (it is flushed when the hardware is powered down), so an ideal system combines long-term, file-based storage with in-memory caching. Additionally, _structured access_ to that data (allowing it to be queried systematically and efficiently) can also greatly improve performance of a webserver.
This role is typically managed by some flavor of database application. Relational databases like the open-source [MySQL](https://www.mysql.com/) and [PostgresSQL](https://www.postgresql.org/), and closed-source [SQL Server](https://www.microsoft.com/en-us/sql-server/sql-server-2019) and [Oracle Database](https://www.oracle.com/database/) remain popular options. However, NoSQL databases like [MongoDB](https://www.mongodb.com/) and [CouchDB](https://couchdb.apache.org/) are gaining a greater market share and are ideal for certain kinds of applications. Cloud-based persistence solutions like [Google Firebase](https://firebase.google.com/) are also providing new alternatives.
## The Stack
This combination of sofware, programming language, along with the operating system running them have come to be referred to as a **stack**. Web developers who understood and worked with all of the parts came to be known as **full-stack developers**.
Clearly, there are a _lot_ of possible combinations of technologies to create a stack, so it was important to know _which_ stacks with which a developer was working. For convenience, the stacks often came to be referred to by acronyms. Some common stacks you will hear of are:
* **LAMP (Linux, Apache, MySQL, PHP)** - the grandaddy of stacks, composed entirely of open-source, free software packages.
* **LEMP (Linux, Nginx, MySQL, PHP)** - basically LAMP substituting the Nginx server for Apache
* **MEAN (MongoDB, Express, Angular, Node)** - Also entirely open-source
Microsoft has thier own traditional stack **ASP.NET**, which is built on Windows Server (the OS), IIS (Internet Information Services, the webserver), a .NET language like C# or Visual Basic, and MSSQL. With the launch of .NET Core, you can now also build a .NET stack running on a Linux OS.
Additonally, frameworks like [Django](https://www.djangoproject.com/), [Ruby on Rails](https://rubyonrails.org/), [Express](https://expressjs.com/), [Laravel](https://laravel.com/), etc. often incorporate preferred stacks (though some parts, specifically the server and database, can typically be swapped out). We'll discuss web serve frameworks in the next chapter.
For the rest of this chapter, we'll discuss the tehniques used by full-stack developers in building dynamic web servers.
{{% notice info %}}
Somewhat confusingly, cloud technologies often replace the traditional webserver role completely, leaving the client-side JavaScript talking to a number of web services. We'll discuss this approach in a few chapters.
{{% /notice %}}
\ No newline at end of file
---
title: "HTML Templates"
pre: "5. "
weight: 50
date: 2018-08-24T10:53:26-05:00
---
While full-stack developers may have chafed at the restrictions imposed by server pages, there was one aspect that came to be greatly valued - the ability to embed script directly in HTML, and have it evaluated and concatenated into the HTML text.
## Template Libraries
This is where template libraries come in. A template library allows you to write your HTML content _as HTML in a separate file_ with a special syntax to inject dynamic programming script. This is often some variation of `<>` or `{}`. This approach allows you to validate the HTML, as the script portions are ignored as unknown tags (when using `<>`) or as static text.
When the server is running, these templates are rendered, evaluating any code and suppling the applicable variables. This process generates the HTML snippet.
This is similar to what server pages do. However, server pages represent an _integrated_ approach - the server page framework defined all aspects of how you could interact with the OS, the web server, and other programs. In contrast, a template library provides the option of using templates within any project - obviously for generating HTML as part of a dynamic website, but potentially for other kinds of applications as well.
Thus, a template rendering library gives us a lot of flexibilty in how and when we use it. For example, in using the [Embedded JavaScript](https://ejs.co/) template library, we could rewrite our directory listing as:
```html
<!doctype html>
<html>
<head>
<title>Directory Listing</title>
</head>
<body>
<h2>Directory Listing for <%= pathname %></h2>
<div style="display: flex; flex-direction: column; padding: 2rem 0">
<% entries.forEach((entry) =>{ %>
<a href="<%= path.posix.join(pathname, entry) %>">
<%= entry %>
</a>
<% }) %>
</div>
<% if (pathname !== "/") { %>
<a href="<%= path.dirname(pathname) %>">
Parent directory
</a>
<% } %>
</body>
</html>
```
Notice how we can embed the JavaScript _directly into the file_. In a Node server, we can use this template to render html:
```js
// Build the dynamic HTML snippets
var data = {
pathname: pathname,
entries: entries,
path: path
};
ejs.renderFile("templates/directory-listing.ejs", data, function(err, html){
// TODO: render the HTML in the string variable html
});
```
While this may _seem_ like just as much work as the concatenation approach, where it really shines is the ability to combine multiple templates, separating parts of the pages out into different, reusable template files. These are typically separated into two categories based on how they are used, _partials_ and _layouts_.
### Partials
A partial is simply a _part_ of a larger page. For example, the entries we are rendering in the listing could be defined in thier own template file, _directory-listing-entry.ejs_:
```html
<a href="<%= path %">
<%= entry %>
</a>
```
And then _included_ in the _directory-listing.ejs_ template:
```html
<!doctype html>
<html>
<head>
<title>Directory Listing</title>
</head>
<body>
<h2>Directory Listing for <%= pathname %></h2>
<div style="display: flex; flex-direction: column; padding: 2rem 0">
<% entries.forEach((entry) =>{ %>
<%- include('directory-listing-entry' {entry: entry, path: path.posix.join(pathname, entry) }) %>
<% }) %>
</div>
<% if (pathname !== "/") { %>
<a href="<%= path.dirname(pathname) %>">
Parent directory
</a>
<% } %>
</body>
</html>
```
While this may seem overkill for this simple example, it works incredibly well for complex objects. It also makes our code far more modular - we can use the same partial in many parts of our web application.
### Layouts
A second common use of templates is to define a _layout_ - the parts that every page holds in common. Consider this template file, _layout.ejs_:
```html
<!doctype html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<%- include('header') %>
<%- content %>
<%- include('footer') %>
</body>
</html>
```
Now our directory listing can focus entirely on the directory listing:
```html
<h2>Directory Listing for <%= pathname %></h2>
<div style="display: flex; flex-direction: column; padding: 2rem 0">
<% entries.forEach((entry) =>{ %>
<%- include('directory-listing-entry' {entry: entry, path: path.posix.join(pathname, entry) }) %>
<% }) %>
</div>
<% if (pathname !== "/") { %>
<a href="<%= path.dirname(pathname) %>">
Parent directory
</a>
<% } %>
```
And we can render our page using the layout:
```js
// Build the dynamic HTML snippets
var data = {
pathname: pathname,
entries: entries,
path: path
};
ejs.renderFile("templates/directory-listing.ejs", data, function(err, content){
if(err) {
// TODO: handle error
return;
}
ejs.renderFile("templates/layout.ejs", {content: content}, function(err, html) {
// TODO: render the HTML in the string variable html
});
});
```
This layout can be re-used by all pages within our site, allowing us to write the HTML shared in common by the whole website once.
Also, while these examples show reading the template files as the response is being generated, most template engines support _compiling_ the templates into a function that can be called at any time. This effectively caches the template, and also speeds up the rendering process dramatically.
### Concise Templating Languages
Some template libraries have leveraged the compilation idea to provide a more concise syntax for generating HTML code. For example, the directory listing written using [Pug](https://pugjs.org/api/getting-started.html) templates would be:
```pug
doctype html
html(lang="en")
head
title= Directory Listing
body
h2= 'Directory Listing for ' + pathname
div(style="display: flex; flex-direction: column; padding: 2rem 0")
each entry in entries
a(href=path.posix.join(pathname, entry)) entry
if pathname !== "/"
a(href=path.dirname(pathname))
Parent directory
```
Concise templating langauges can significantly reduce the amount of typing invovled in creating web pages, but they come with a trade-off. As you can see from the code above, learning Pug effectively requires you to learn a new programming language, including its own iteration and conditional syntax.
{{% notice info %}}
EJS is just one template library available in JavaScript. Some of the most popular ones include:
* [Moustache](https://mustache.github.io/)
* [Underscore](http://underscorejs.org/)
* [Handlebars](https://handlebarsjs.com/)
* [Nunjucks](https://mozilla.github.io/nunjucks/)
* [Underscore](http://underscorejs.org/)
* [Pug](https://pugjs.org/api/getting-started.html)
It is useful to compare how these different libraries approach templates as there are often large differences, not only in syntax but also in function.
{{% /notice %}}
## Components
A newer approach, popularized by the [React](https://reactjs.org/) framework, emphasizes building _components_ rather than _pages_. A component can be thought of as a single control or widget on a page. While conceptually similar to the partials described above, it organizes its structure, styling, and scripting into a cohesive and reuseable whole.
This represents a move away from the separation of concerns we described earlier. It often incorporates aspects of [declarative programming](https://en.wikipedia.org/wiki/Declarative_programming) rather than thinking of programming in terms of control flow. This component-based approach also lends itself to developing [progressive web applications](https://en.wikipedia.org/wiki/Progressive_web_application), which only download the script needed to run the portion of the app the user is interacting with at a given time.
As this approach is significantly different from the more traditional templating libraries, we'll discuss these ideas in the next chapter.
\ No newline at end of file
---
title: "Dynamic Pages"
pre: "6. "
weight: 60
date: 2018-08-24T10:53:26-05:00
---
We've already written a number of functions that take in a request and response object, and determine the correct response to send. This includes our `serveFile()`, and our `listDirectory()`. We can create dynamic pages in much the same way - by writing a custom function to serve the dynamic page.
For example, a very simple dynamic page could be created with this function:
```js
function serveTime(req, res) {
var html = `
<!doctype html>
<html>
<head>
<title>Server Time</title>
</head>
<body>
<h1>Time on the server is ${new Date()}</h1>
</body>
</html>
`;
req.writeHead(200, {
"Content-Type": "text/html",
"Content-Length": html.length
}).end(html);
}
```
But let's expand our thinking to tackle a more invovled website
With a template library, we can start thinking about how to better structure our software to produce the web pages that our dynamic web application consists of. The template library can be used to produce the HTML we need to serve, now we need to consider exactly which templates to use, in what combination, and what data needs to be provided to them.
\ No newline at end of file
---
title: "Query and Hash Strings"
pre: "6. "
weight: 60