Routes, Route Parameters, URL Parameters
Last class we looked at the HTTP protocol, including requests, responses, and their structures. We also looked in a bit more depth at request types and status codes and their meanings.
In this class we're going to look in a bit more depth at URLs and routes, including how we can use them to change the data or pages we give back to clients. We're also going to look at GET parameters and how we can use them to process data from client requests.
Structure of a URL
A URL has several different parts, and it's helpful to understand each of them for our purposes.
The protocol is the way you access the resource, which we covered last time. It can be many different values, but standard examples supported by the browser are https://
, http://
, and ftp://
.
The domain is the next part of the URL and specifies the exact site we're visiting (i.e. which server we're connecting to). It has several parts, which we'll explain below. An example is www.google.com
.
The route is indicated by /
in a URL and tells the server which resources we want to access. Routes can be infinitely nested: for example www.corporation.com/business/branch/department/office/employee
could be used to get information about a particular employee working for a large company.
The parameters or query string are used to provide additional information to a specific page. For example: www.shopping.com/view_item?id=abc
might bring up details of a particular product using a standard template for the view_item
route.
The fragment is a part of a specific URL specified by #
. Usually these are used to make it possible to navigate to specific elements on a page (like section headers). For example, https://www.example.com/my_page#heading
will take you to a heading on my_page
.
Parts of a Domain Name
Domains are usually written in reverse order, which can make them a little confusing. A domain name is written as one or more subdomains, a domain name, and one or more TLDs.
The subdomain is a part of a domain name set by whoever controls the DNS records. This can be any value, but common ones are: app.example.com
, mail.example.com
, www.example.com
, admin.example.com
and others.
You can also nest subdomains like app1.apps.example.com
, although this is unusual.
Different subdomains are often different websites with different systems, while routes usually point to different resources within a single system.
The top level domain (TLD) is the domain extension for a number of domain names. For example: .com
, .co.uk
, .ru
, or .london
are all valid TLDs.
In the original concept of domain names, the country code was supposed to come after the TLD (so .co.ru
and .co.us
would be valid domains). In practice, however, only a limited number of TLDs are in active use.
Knowledge Check
- Give an example of each of the following:
- A protocol
- A domain name
- A top-level domain
- A route
- A query string
- What's the usual use of a fragment such as
#about
after a URL? - Is
hello.world.example.com
a valid domain name?
Route Parameters in Express
When we're developing websites or other multi-page applications (MPAs), we usually let our webserver handle routing for us. Common web servers like nginx and Apache will translate a directory structure like:
/static
/www
/index.html
/about
/index.html
/careers.html
Into routes which look like:
example.com
example.com/about
example.com/about/careers
However, if we're serving content or data which doesn't neatly map to a directory structure (for example, because it pulls from a database), we'll need to write a program which gives the correct information back based on a route.
We can do this by using route parameters. Route parameters are used to capture variables from the route part of the URL, which can be used to change which content or data is retrieved on a given route. They can be set up by using :parameter
in any part of a route, and retrieved using req.params.parameter
.
Let's look at an example. Make a copy of the project for this class via git
or by download. Now take a look at /src/index.js
.
app.get("/product/:id", function (req, res) {
const page = nunjucks.render("product.html", {product: products[req.params.id]})
res.setHeader("Content-Type","text/html")
res.send(page)
})
In this example we take the id
parameter from the route, and use it to render the correct data in the product.html
template. We're using nunjucks, a template language, to make it easier to display data in our webpages.
If you take a look at product.html
you'll find that it's fairly barebones. Our data is coming from products.json
! The id
parameter tells index.js
which product in products.json
we're interested in, then lets nunjucks render it.
Exercise
- Try adding some more products to the store, or modifying existing products in
products.json
. Observe that you can just update the JSON file and the index and product pages will update with it. - Add an additional route at
/api/product
with a GET method. Rather than returning a webpage this will return a list of all the products in JSON format. - Change the route at
/api/product/PRODUCT_ID
so that it returns details of the product by default.
Query Parameters
Often when using websites, you'll see parameters as part of the URL which are not part of the route. For example, a typical YouTube URL looks like:
https://www.youtube.com/watch?v=o-YBDTqX_ZU&t=0
In this example the domain name is www.youtube.com
, and the route is /watch
. v
and t
are parameters: v
is the identifier for the video, while t
is the timestamp to start the video at in seconds.
If you setup a form with <form method="GET">
, then it will insert parameters sent from the form into the url in the form action
.
Both the server and the client can read these parameters, which differs from POST
requests (which the client can't read after sending). This can be convenient in a range of situations.
However, as information in the URL parameters can be directly read by the user and by the frontend, they're not a good place to put anything you want to be secure. Keep usernames, passwords, tokens, and other authentication tokens in POST requests or headers.
In Express, we can access the query string for a URL by using req.query.parameter
. For example, in our Express server, we look on the /api/product/:id
route to check if it has a size
parameter. If it does, we send back some information for the frontend to render. If not, we return a 400 error code.
app.get("/api/product/:id", function(req, res) {
if(Object.hasOwn(req.query,"size")) {
res.status(200)
res.setHeader("Content-Type","text/plain")
return res.send(products[req.params.id].styles[req.query.size])
}
return res.sendStatus(400)
})
Exercise
- Add some more sizes to the products in the shop using
products.json
. - Add a new section to
products.json
for each size, which specifies different colors for each size and has a description for each. For example,t-shirt
andblue
andsmall
might lead to"A small blue t-shirt
as a description. - Modify the
api/product/:id
route to take the color parameter, cross-reference it with thesize
parameter, and return the matching string. - Modify
product.html
to successfully issue fetch requests and render out descriptions for each size and color combination.
Assignment
In digital marketing, a UTM is an identifier given to different campaigns or sources of traffic. They can be used by companies to analyse which campaigns are the most successful and which channels bring the most users, letting them optimise their marketing spend effectively.
The URL for a UTM link looks like this:
https://www.example.com/landing-page?utm_campaign=my_cool_campaign&utm_source=facebook&utm_medium=social
However, companies often don't want to paste extremely long URLs into their social media campaigns, and will instead use link shorteners to generate links which look like this:
https://www.example.com/fb/cool
These links will redirect to the original UTM link, with all the UTM parameters set correctly, but are shorter and more attractive in social campaigns.
Your assignment today has several parts.
- Create two HTML landing pages for your campaign. They can just be a page saying "Hello world" if you like.
- Make an Express server to return your landing page on a given route. When someone requests the landing page, it should check for UTM parameters and log them out from the Express server.
- Create a route which replicates a link shortener. It should take route parameters corresponding to the following format:
URL/CAMPAIGN/SOURCE
. For example,localhost:3000/fb/cool
. It should then redirect to your landing pages with the UTM parameters prefilled. Add at least 2 different UTM campaigns and 2 different UTM sources to the final URL.