Setup
Before starting this lab, ensure that you have:
- Accept the Github Classroom assignment and clone this repo that contains stencil code for lab5.
For this lab, we have attached our completed version of lab4 in the repo but feel free to reuse your version of the MadLibs game from lab4.
If you want to use your own code, you should put your HTML files in the
views
directory and put your static files like images, Javascript scripts and Stylesheets in the
public
directory.
Run
npm install
in your cloned repo to install necessary dependencies and use
npm run start
to start you server. Visit the localhost port shown from this command. We enabled hot reloading using
nodemon
which automatically restarts the node application when file changes in the directory are detected.
You can think of nodemon as a replacement wrapper for node. To use nodemon, replace the word node on the command line when executing your script.
Overview
For this lab, you will be working in groups to recreate a MadLibs website using the Express Framework to create your own mini web server. The website should contain 3 pages: a MadLibs page, a results page, and a 404 error page.
In the previous assignments, you mainly worked with Single Page Applications : in assignment 2, you created a dynamic webpage displaying the tweets while in lab 4 you used multiple Vue components and has in-page routes using Vue Router. In other words, the entire application resided in a single endpoint, often the root route. Moreover, every web application we built was a static site where all code was client-side and there was no dedicated server.
However, single route and static web apps are often not sufficient when we need to build a full-fledged server with many API endpoints and database connections. That's why we turn to Node.js for building the server-side of a web application!
Requirements
- Build the web server using Express.
-
Routes:
-
/madlibs
This should render themadlibs.html
page. This page should be your game page where the user fills in all the inputs of the randomly picked MadLib (the completed Madlib paragraph should not be displayed in this page). There should also be an explicit way (a button for example) that sends the user to the/results
page. -
/results
This should render the results page, which should have the completed MadLib paragraph (aka with the user input from/madlibs
included). - A catchall route that handles 404 requests.
-
Hints
-
We have provided a completed version of Madlib using Vue in our stencil code. There are several ways to go about this lab and you can solve it however you'd like but here are two standard approaches for this lab:
-
Refactor Vue.js code to communicate with the backend and render
/madlibs
and/results
page. - Implement madlibs using just HTML, JS, Node.js and Mustache/Handlerbar templating engine. For this approach, you can feel free to copy parts of the code you find relevant from the Vue components we have provided in the stencil.
-
Refactor Vue.js code to communicate with the backend and render
- When you enter a URL into the browser, you are actually making a GET request to the corresponding route on the server. You can also redirect to another page programmatically with Javascript .
-
To show specific HTML pages when you visit a certain URL, you can send those files to users, by using:
response.sendFile(PATH_TO_FILE, {root: __dirname}}
.Without
{root: __dirname}
, thePATH_TO_FILE
must be an absolute path. With{root: __dirname}
, however,PATH_TO_FILE
can be a relative path with respect to the root directory, since the root gets prepended to the path that you specify.You can refer to the API for
res.sendFile
for more information or take a look at how we registered the route for themadlibs
page inserver.js
.Recall from the prelab that
__dirname
is a property provided by Node.js and refers to the absolute path of the directory containing the currently executing file. Look at this post for more information. -
From a security perspective, it is best practice to send data in a POST request rather than a GET request since the latter will encode the data as plaintext in the URL! Read more about the comparison of different HTTP methods here .
-
There are multiple ways to construct the madlibs
/results
page:-
We send the madlib inputs as a GET request to the endpoint
/results
.-
This gives every madlib input a unique identifier (an index for example in the
name
field) in themadlibs.html
page since named form inputs are encoded as URL parameters in GET requests. To keep track of which MadLib is selected, we use a hidden form input specifying the MadLib index. -
Build the MadLib paragraph in the server side:
-
on the server side: dynamically build a
results
HTML page with the completed MadLib paragraph in the route handler for/results
using the form inputs values retrieved fromreq.query
and send the HTML string withres.send
. - on client side: nothing needs to be done in client side since the response is a HTML string and will be automatically rendered.
-
on the server side: dynamically build a
-
Build the MadLib paragraph in the client side:
-
on server side: send the template
results.html
file withres.sendFile
- on client side: there are different ways to dynamically build the MadLib paragraph in the frontend Javascript code. You can use the URL parameters retrieved from URLSearchParams or the solution in our stencil code.
-
on server side: send the template
-
This gives every madlib input a unique identifier (an index for example in the
-
To send madlib inputs as a POST request to the endpoint
madlibs
, we use a cookie to store a unique identifier generated by a random string generator function uuid.Cookies are kept by the browser and sent automatically every time a request is made to the same domain and using cookies allows you to track a user among multiple pages.
We have installed cookie-parser for you and have handled this cookie logic. If you want to explore this more, you can access cookies in the server handler using
req.cookies
.When receiving the POST request from
madlibs.html
, the server can store a mapping from the identifier to the inputs in a global Map object in the server (think of this as your database). Whenresults.html
is rendered, an additional request can be made with fetch API to obtain a JSON response of the inputs. To send a JSON response from the server, you can use res.json. - Similar to the cookies approach, you can store the unique identifier in Local Storage to keep track of a user among different pages.
-
We send the madlib inputs as a GET request to the endpoint
-
If you have a link to a static file (image, Stylesheet, Javascript script) that is not loaded, you should make sure it is put inside the
public
directory and properly references with relative paths. Look at how we load themadlibs.js
file inmadlibs.html
and how we load other components frommadlibs.js
for reference.
Handin Instructions
Hand in your code for this lab via Gradescope. Please upload your code to GitHub and submit through Gradescope. Only one team member should upload their local version of the code and then assign group members after submission.
Lab Handins on Course Website
Keep in mind that each submission for this lab will be anonymously displayed on the course website, so please keep this in mind and do not put any identifying information in your handin.