Lab: Routing

In this lab, we are demonstrating the basic of GET and POST routes in Node.js. We are not building a web app. We are observing how HTTP requests get dispatched to code.

Step 1: The smallest possible server

1
2
3
4
5
6
7
8
9
const http = require('http');

const server = http.createServer((req, res) => {
  res.end('Hello\n');
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

Step 2: Inspect method and URL

1
2
3
4
5
6
7
8
9
10
const http = require('http');

const server = http.createServer((req, res) => {
  console.log(req.method, req.url);
  res.end('Check the console');
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});
1
2
3
4
5
6
7
root@4285d71fdcf6:/apps/3-lab-routes# node server.js 
Server running on port 3000
GET /
GET /favicon.ico
GET /
GET /favicon.ico

Exercise

Open a new terminal and run the following command: curl http://127.0.0.1:3000, and observe that the line GET /favicon.ico no longer appears. Search for an explanation.

Step 3: First real route: GET

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method === 'GET' && req.url === '/') {
    console.log(req.method, req.url);
    res.end('Home page\n');
  } 
  else if (req.method === 'GET' && req.url === '/users') {
    console.log(req.method, req.url);
    res.end('List users\n');
  } 
  else {
    res.statusCode = 404;
    console.log(req.method, req.url);
    res.end('Not Found\n');
  }
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

Step 4: POST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method === 'GET' && req.url === '/') {
    console.log(req.method, req.url);
    res.end('Home page\n');
  } 
  else if (req.method === 'GET' && req.url === '/users') {
    console.log(req.method, req.url);
    res.end('List users\n');
  } 
  else if (req.method === 'POST' && req.url === '/users') {
    console.log(req.method, req.url);
    res.end('Create a user\n');
  }
  else {
    res.statusCode = 404;
    console.log(req.method, req.url);
    res.end('Not Found\n');
  }
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

1
2
curl http://localhost:3000/users
curl -X POST http://localhost:3000/users

Method is part of the route identity

  • A route is not a URL.
  • A route is method + URL.

Step 5: GET vs POST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method === 'GET' && req.url === '/') {
    console.log(req.method, req.url);
    res.end('Home page\n');
  } 
  else if (req.method === 'GET' && req.url === '/login') {
    console.log(req.method, req.url);
    res.end('show login form\n');
  } 
  else if (req.method === 'POST' && req.url === '/login') {
    console.log(req.method, req.url);
    res.end('process login\n');
  }
  else {
    res.statusCode = 404;
    console.log(req.method, req.url);
    res.end('Not Found\n');
  }
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

Step 6: Read POST Data

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const http = require('http');

const server = http.createServer((req, res) => {
  if (req.method === 'GET' && req.url === '/') {
    console.log(req.method, req.url);
    res.end('Home page\n');
  } 
  else if (req.method === 'GET' && req.url === '/login') {
    console.log(req.method, req.url);
    res.end('show login form\n');
  } 
  else if (req.method === 'POST' && req.url === '/login') {
    let body = '';
    req.on('data', chunk => {
      body += chunk;
    });

    req.on('end', () => {
      console.log(req.method, req.url);
      console.log('POST body:', body);
      res.end(`Received: ${body}`);
    });
  }
  else {
    res.statusCode = 404;
    console.log(req.method, req.url);
    res.end('Not Found\n');
  }
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});

1
2
3
4
curl -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "username=linh&password=secret" \
  http://localhost:3000/login

Step 7: Routing Logic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const http = require('http');

function handleGet(req, res) {
  if (req.url === '/') {
    console.log(req.method, req.url);
    res.end('Home page\n');
  } else if (req.url === '/login') {
    console.log(req.method, req.url);
    res.end('show login form\n');
  }
}

function handlePost(req, res) {
  if (req.url === '/login') {
    let body = '';
    req.on('data', chunk => {
      body += chunk;
    });

    req.on('end', () => {
      console.log(req.method, req.url);
      console.log('POST body:', body);
      res.end(`Received: ${body}`);
    });
  }
}

const server = http.createServer((req, res) => {
  if (req.method === 'GET') handleGet(req, res);
  else if (req.method === 'POST') handlePost(req, res);
});

server.listen(3000, () => {
  console.log('Server running on port 3000');
});