๐Ÿ”Œ Servers

Node and middleware and so on

Servers block viewer

This block viewer lets you flick through all the existing blocks in the Servers folder so you can choose what parts to add to your pages and what parts you might want to create, revise, or leave out.

It's literally just an alphabetical list of whatever is in this folder.

๐Ÿ• GET

Learning Objectives

GET /movies should return all the movies

In server.js, create a GET /movies endpoint that returns all the movies (see below for some sample data).

app.get("/movies", (req, res) => {
  res.send(moviesData);
});
Copy sample movie data
const movies = [
  {
    id: 1,
    title: "The Godfather",
    certificate: "18",
    yearOfRelease: 1972,
    director: "Francis Ford Coppola",
  },
  {
    id: 2,
    title: "The Shawshank Redemption",
    certificate: "15",
    yearOfRelease: 1994,
    director: "Frank Darabont",
  },
  {
    id: 3,
    title: "Schindler's List",
    certificate: "15",
    yearOfRelease: 1993,
    director: "Steven Spielberg",
  },
];

๐Ÿงช Run and test

  1. npm run dev
  2. Open Postman
  3. Make a GET request to http://localhost:3000/movies

๐Ÿ• GET single movie

Learning Objectives

GET /movies/:movieId should return a single movie (that matches the passed movieId)

Sometimes, we do not want to list all the information in one request, maybe we only want to get the information related to a single movie. Imagine a page to display the details of one movie. We’d call the server, get all movies, then filter the one we need client-side. It would be more effective to tell the server to just return the one movie we are interested in.

We will now add a new endpoint to return only a single movie GET /movies/:movieId. In this case, movieId will tell us what movie we can return. The call will be GET /movies/10 and that will return the movie with that has movieId: "10".

This endpoint has something different. The endpoint /movies/:movieId has a dynamic part. The movieId will vary depending on what the client sends.

In server.js, create a GET /movies/:movieId endpoint that returns a single movie. The movieId will be passed as a parameter in the URL.

app.get("/movies/:movieId", (req, res) => {
  const movieId = req.params.movieId;
  const movie = moviesData.find((movie) => movie.movieId === movieId);
  res.send(movie);
});

๐Ÿงช Run and test

  1. Save your changes
  2. Make a GET request to http://localhost:3000/movies/10

๐Ÿ’ช๐Ÿพ CRUD Challenges

CHALLENGE 1:

Return the old version of the object you updated as well as the new value in the response

CHALLENGE 2:

Validate the request body to make sure the ID can’t be updated and that users can’t add additional fields

CHALLENGE 3:

Persist your changes to file so that you are able to return your updated values even after you restart the server

๐Ÿ“จ POST

Learning Objectives

POST /movies should save a new movie

In order for our server-side to receive and use the data sent by the client, we will need to install and use a middleware.

The JSON middleware makes it easy for our route handlers to read JSON data from the request. If the Content-Type request header indicates that the request body contains JSON data then the middleware calls JSON.parse to convert the request body into a JavaScript data structure.

To register the JSON middleware, add the following to the server code:

app.use(express.json()); // before our routes definition

In server.js, create a POST /movies endpoint that saves a new movie. The movie will be passed as a JSON object in the request body.

Step by step if you get stuck
  1. Add the following code to server.js:
app.post("/movies", (req, res) => {
  const newMovie = req.body;
  moviesData.push(newMovie);
  res.send("movie added successfully!");
});
  1. Open Postman and create a new request.
  2. Set the Request Type to POST.
  3. Enter the URL for your endpoint, which should be http://localhost:3000/movies.
  4. Set the Body Type to raw and format to JSON (application/json).
  5. Enter the movie Data in the body of the request as JSON:
{
  "id": "13",
  "title": "Boyhood",
  "certificate": "15",
  "yearOfRelease": 2014,
  "director": "Richard Linklater"
}
  1. Click Send.
  2. You should see the movie you just created in the response.

๐Ÿ“จ PUT

Learning Objectives

PUT /movies/:movieId should update a movie (that matches the passed movieId)

This means that PUT /movies/2 should update an movie with the id 2 and return 200 with JSON { success: true } to the user.

The code should look something like this:

app.put("/movies/:movieID", (req, res) => {
  console.log("PUT /movies route");
});

Remember, you have got to update the movie, not add it to the list.

Test that your API works by updating one of the movies.

๐Ÿ“ฎ ๐Ÿงช Test Examples in Postman

Learning Objectives

You will need to create an account with Postman to complete this task. Follow along with the video Writing Tests in Postman with Examples.

๐Ÿ“ฎ Interactive Postman Workspace

activity

  1. Given a user wants to see all the movies, when they make a GET request to /movies, then they should receive a list of all the movies.

  2. Given a user wants to see a single movie, when they make a GET request to /movies/:movieId, then they should receive a single movie.

  3. Given a user wants to add a movie, when they make a POST request to /movies, then they should receive a success message.

  4. Given a user wants to update a movie, when they make a PUT request to /movies/:movieId, then they should receive a success message.

Building the server

Learning Objectives

The first thing we need to do is build our server. You will often need to build a server when writing back-end code. You can write a server in plain JavaScript, but Express is simpler to work with.

1. Create a server.js file

Let’s build our server! In your project, create a new file called server.js. This is where all our server code is going to live.

touch server.js

2. import the express library

We just installed Express, but we need to make sure it is included in this file specifically so we can use its methods. In Node.js, when you want to use Express in another file, you must import it.

To require Express, write the following inside server.js:

import express from "express";

โš ๏ธ warning

Sometimes you will see require instead of import. This is because require is the old (CJS) way of importing packages in Node.js and not all environments (like runkit) are updated yet. If you see require in the curriculum, probably use import instead.

CJS syntax: const express = require("express"); MJS syntax: import express from "express";

3. Initialise the server

To initialise our server, we need to call the express() function. This will create an Express application for us to work with.

Add the second line of code to your server.js file:

const express = require("express");
const app = express();

4. Start ’listening’ for potential requests

One more step left, we need to set a port for our server to listen to. Think of a port as a door number: any requests that come to the server will come via that door. Setting a port will allow us to find where our server is running.

We use the app.listen method to do this. This method takes two arguments: a port and a callback function telling it what to do once the server is running.

Need clarification? Read more about the app.listen method in the Express documentation.

We’re going to run our server on port 3000, and add a console.log in the callback function. Update your server.js file, calling the app.listen method:

const express = require("express"); const app = express(); app.listen(3000, () => { console.log("Server is listening on port 3000. Ready to accept requests!"); });

5. Switch the server on!

You’ve built your server, but it isn’t running yet. We need to run a command in the terminal to do this. We are going to use the node keyword to run the server file.

Type the following command in your terminal:

node server.js

If you see this, congratulations! You have built yourself a server!

success

6. npm script

To exit the running the server, type ctrl + c. Instead of running the server with node server.js everytime, we can create an alias for it in package.json.

Under the scripts property, add start: node server.js. We can now run our server using npm start which will be an alias (a shortcut) to node server.js.

Go to the terminal and type npm start and make sure that the server still runs.

Communicating with the server

Learning Objectives

Now that we’ve built the server, we need to communicate with it. We are going to control the server with handler functions.

What is a handler function?

When a request reaches the server, we need a way of responding to it. In comes the handler function. The handler function receives requests and handles them, hence the name.

The handler function is always called with a request and response object. The response object is what gets sent back to the client. It contains the information that gets displayed in the web page. You can decide what to send back in your response.

What does a handler function look like in Express?

The get() method is one of the methods used to define a handler function in Express. It takes two parameters: the endpoint at which to trigger an action, and the handler function that tells it exactly what to do.

Here’s an example:

// req is the Request object, res is the Response object
// (these are variable names, they can be anything but it's a convention to call them req and res)
app.get("/", (req, res) => {
  res.send("Hello World!");
});

Here, we are telling our server to respond with “Hello World!” when someone tries to access the webpage.

1. Create your own handler function

Add a handler handler function to send back a message to the client. To do that, use the Express send() method. This will update the response object with the message.

Update your handler function:

const express = require("express"); const app = express(); app.get("/", (req, res) => { res.send("Yay Node!"); }); app.listen(3000, () => { console.log("Server is listening on port 3000. Ready to accept requests!"); });

console.log the request object inside the handler function.

  1. Restart your server
  2. Send the request again with Postman
  3. Go to your terminal to see what it looks like.

You should see a lot of data come through!

2. Check it out in Postman

Quit your server in the terminal with ctrl + c. Then restart it to run your new changes.

node server.js
  1. Open Postman
  2. Send a GET request to http://localhost:3000.

If you see your message in Postman, congratulations! You just sent your first response from the server.

Checkpoint

Do you understand all these terms? You should be able to see examples of them in Postman

CRUD

Learning Objectives

We will build a CRUD API. CRUD stands for Create, Retrieve, Update, Delete. If you think about it, this is what most applications do:

โœจ Create some “resources” ๐Ÿ• Retrieve them (GET them) ๐Ÿ“จ Update them ๐Ÿ—‘๏ธ Delete them

๐ŸŽฏ Goal

Our API will manage movie data. It will:

โœจ Create a new movie, ๐Ÿ• Retrieve a list of movies or a single movie

We will build these endpoints:

  1. GET /movies should return all the movies
  2. GET /movies/:movieId should return a single movie (that matches the passed movieId)
  3. POST /movies should save a new movie

๐Ÿ‘‰ Fork the Node-Starter-Kit repo and clone it to your computer. Then run npm install to install the dependencies.

CRUD Again

Learning Objectives

We are building a CRUD API. CRUD stands for Create, Retrieve, Update, Delete. If you think about it, this is what most applications do:

โœจ Create some “resources” ๐Ÿ• Retrieve them (GET them) ๐Ÿ“จ Update them ๐Ÿ—‘๏ธ Delete them

๐ŸŽฏ Goal

Our API will manage movie data. It will:

โœจ Create a new movie, ๐Ÿ• Retrieve a list of movies or a single movie ๐Ÿ“จ Update a movie

We will build this endpoint:

  1. PUT /movies/:movieId should update a movie (that matches the passed movieId)

๐Ÿ‘‰ You should already have a project using the Node-Starter-Kit. If not, do last week’s prep before you go on.

Install Postman

Learning Objectives

Install Postman

Troubleshooting

If you get:

error while loading shared libraries: libgconf-2.so.4: cannot open shared object file: No such file or directory

You may first need to run this in the terminal:

sudo apt-get install -y libgconf-2-4

If you get a blank screen when you open Postman, try logging out of the app and choosing “Use the Lightweight API Client” instead.

For now you will only need the Lightweight API Client.

Alternatives

If you have an old computer you might find Postman being very slow or becoming unresponsive. In this case you could try:

  • Thunder Client: this VS Code extension has a similar user interface to Postman
  • Hoppscotch: this web app runs in the browser.

Introduction to Express

Learning Objectives

We have already learned about the Node.js runtime environment and how it allows us to run JavaScript code outside of the browser. We have also learned about the Node Package Manager (npm) and how it allows us to download and use other people’s code in our own projects.

Now we will learn about Express, a Node.js framework that helps us to build web servers and APIs.

๐Ÿ’๐Ÿผโ€โ™‚๏ธ What is a web server?

A web server is software that accepts requests for web pages, assets, APIs, and other network resources from client programs like web browsers. When a browser requests a web page, the server finds the desired content and returns the appropriate response.

๐Ÿ—บ๏ธ Explore the web server

Let’s investigate a web server made in Node.

//Load the 'express' library to easily handle HTTP conversations: const express = require("express"); const app = express(); //Register some handlers for different routes. app.get("/", (request, response) => { response.send("Hello thar!"); }); app.get("/two", (request, response) => { response.send("Another route"); }); app.get("/numbers", (request, response) => { const someData = [1, 2, 3]; response.json(someData); }); //Tell the server to start listening for requests. app.listen(3000);

activity

Investigate the different parts of the Node App

  • require on Line 3
  • express() on Line 5
  • app.get() on Line 12, 26 and 20
  • app.listen() on Line 29
  • response.send() on Line 13 and Line 17
  • response.json() on Line 22

Can you work out what each those lines are doing? Write down your predictions.

๐Ÿ“š Stretch Goals: make and run a local copy

๐Ÿ˜๏ธ Run the Simple Server locally

activity

  1. Fork and clone: https://github.com/CodeYourFuture/Node-Exercises.
  2. cd into the cyf-simple-express directory.
  3. Run npm install to install the dependencies.
  4. Once everything is installed, start the server with npm start

๐Ÿ’ก tip

Access your local API by going to http://localhost:3000

๐Ÿ’…๐Ÿฟ Modify the Server

activity

Now try to modify the server.js code to do something different.

Examples:

  1. Say “Hello Margarita”, instead of “Hello thar!”
  2. Make it return an array of strings as json.
  3. Make it return the current time
  4. Advanced: make it return whatever you want!

Make a Node Project

Learning Objectives

๐Ÿ†• Create a new repo

1. Go to github.com/new and choose these settings (click to expand):
QuestionAnswer
Repository templateNo template
OwnerYOUR_GITHUB_USERNAME
Repository nameExpress-101
DescriptionMy first Express web server
VisibilityPublic
Initialize this repository with::white_check_mark: Add a README file
Add .gitignoreNode
Choose a licenseMIT License
  1. Click Create repository

โ™Š Clone your repo

Clone your newly made repo to your local machine. You are going to be working in this folder for the rest of the study session.

Initialize your project

๐Ÿ“ note

  1. Open your project in VS Code
  2. Open the terminal
  3. Run npm init -y to initialize your project
  4. Run npm install express to install Express
  5. Commit your changes and push them to GitHub

Start your README

๐Ÿ“ note

  1. Open README.md in VS Code
  2. Add a title and description
  3. Add a link to the Express documentation
  4. Write a sentence about what you are going to build
  5. Commit your changes and push them to GitHub

Query Parameters

Learning Objectives

So, what is a query parameter?

A query string is the part of a URL (Uniform Resource Locater) after the question mark (?). It is meant to send small amounts of information to the server via the url. This information is usually used as parameters to query a database, or maybe to filter results.

Here is an example of a URL with query strings attached: https://stackabuse.com/?page=2&limit=3

โ“ Detect Query Parameters

Try sending different responses at different endpoints. Remember the app.get() method? To set up routing in your server, we need to repeat this method with different endpoints.

app.get("/", (req, res) => {
  let searchQuery = req.query.search;
  res.send("Hello World! You searched for " + searchQuery);
});

Test this endpoint with query parameters: http://localhost:3000?search=hello

Now your turn!

activity

Add some code so that your server returns the amount of chocolate that you want from your /chocolate endpoint.

๐Ÿงช Acceptance Criteria

Given a chocolate endpoint When I load http://localhost:3000/chocolate?amount=3 Then I see the message “Gimme 3 chocolates!”

โ“โ“ Multiple Query Parameters

What if we want to detect and read multiple parameters? If we use a URL from earlier as an example, here is how we would send multiple query parameters:

https://api.sunrise-sunset.org/json?lat=51.5311&lng=0.0481

Here we have one parameter called “lat” and another “lng”. The first parameter starts with ? All subsequent parameters start with &.

Here is how we would do that in Node:

app.get("/json", (req, res) => {
  let lat = req.query.lat;
  let lng = req.query.lng;
  res.send(`You searched for Lat: ${lat} and Lng: ${lng}`);
});

activity

Add some code so that your server takes 2 values that we will multiply together and return the value.

๐Ÿงช Acceptance Criteria

Given a multiply endpoint When I call http://localhost:3000/multiply?value1=2&value2=10 Then it returns a value of 20

Routing

Learning Objectives

At the moment our server only does one thing. When it receives a request from the / endpoint, it sends back the same response: “Yay Node!”.

๐Ÿ’ก tip

Try typing http://localhost:3000/node and see what happens.

However by making use of endpoints, we can make the server send different responses for different requests. This concept is called routing.

What is an endpoint?

An endpoint is the part of the URL which comes after /. For example: /chocolate is the “chocolate” endpoint. It’s the URL to which you send a request. It’s the end point of the resource path.

What is a URL?

sequenceDiagram participant U as URL participant P as Protocol participant H as Host participant Po as Port participant R as Resource Path Note over R: (Endpoint) participant Q as Query Params U->>P: http:// U->>H: www.domain.com U->>Po: :1234 U->>R: /path/to/resource U->>Q: ?a=b&x=y

Create your own endpoints and send different responses

We’re going to try sending different responses at different endpoints. Remember the app.get() method? To set up routing in your server, we need to repeat this method with different endpoints.

For example:

app.get("/", function (req, res) {
  res.send("Hello World!");
});

app.get("/chocolate", function (req, res) {
  res.send("Mm chocolate :O");
});

activity

Add some code so that your server sends one message when the endpoint is /node and another one when it’s /codeyourfuture.

Set up Render

Learning Objectives

Let’s try out using Render to host our Node.js application. There are many platforms that you can use to host your Node.js application, but we’re using Render right now because it’s free. If your cohort has found a better option, please use that, and contribute your setup guide back to the curriculum.

activity

  1. Fork https://github.com/CodeYourFuture/CYF-React-Express-Template
  2. Create an account with Render and choose GitHub as your auth.
  3. Create a new Web Service and choose Build and deploy from a Git repository
  4. Connect your forked repo to Render