Introdução ao Express.js
Definição
Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.
Características
- Rápido
- Minimalista
- Flexível
- Não opinativo
- Usado para montar APIs
- Alguns frameworks são baseados no Express
Exemplo de Express.js
hello-simple
├── package.json
├── requests.http
└── src
    └── index.jshello-simple
├── package.json
├── requests.http
└── src
    └── index.jsFluxo da aplicação hello-simple:

Código da aplicação hello-simple:
import express from 'express';
 
const app = express();
 
app.get('/', (req, res) => {
  res.send('Hello World!');
});
 
app.listen(3000, () => {
  console.log(`Example app listening at http://localhost:3000`);
});
 import express from 'express';
 
const app = express();
 
app.get('/', (req, res) => {
  res.send('Hello World!');
});
 
app.listen(3000, () => {
  console.log(`Example app listening at http://localhost:3000`);
});
 Para a criação do arquivo package.json use este comando no terminal:
$ npm init -y$ npm init -yAdição do pacote express.js como dependência do projeto e dos scripts de execução do projeto:
$ npm install express$ npm install express{
  "name": "hello-simple",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js",
    "dev": "node --watch src/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  }
}
 {
  "name": "hello-simple",
  "version": "1.0.0",
  "description": "",
  "type": "module",
  "main": "src/index.js",
  "scripts": {
    "start": "node src/index.js",
    "dev": "node --watch src/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  }
}
 Para executar o projeto use algum destes comandos:
$ node src/index.js$ node src/index.js$ npm start$ npm startJá a execução no modo watch (No VSCode use o NPM Scripts para executar em modo debug):
$ npm run dev$ npm run devDepende da versão do node.js, o modo watch precisa de um pacoto como o nodemon para funcionar:
 "scripts": {
    ...
    "dev": "nodemon src/index.js"
  }, "scripts": {
    ...
    "dev": "nodemon src/index.js"
  },$ npm install nodemon -D
$ npx nodemon src/index.js
$ npm run dev$ npm install nodemon -D
$ npx nodemon src/index.js
$ npm run devJá para testar as requisições use o arquivo requests.http do plugin Rest Client do VSCode:
### Get Hello World
 
GET http://127.0.0.1:3000/
 ### Get Hello World
 
GET http://127.0.0.1:3000/
 
Cuidado no git para não versionar a pasta
node_modules/, use o arquivo.gitignorepara desconsiderar a pasta.
node_modules
node_modules
Rotas da Aplicação
Rotas:
- /hello/en=>- Hello World!
- /hello/pt=>- Olá Mundo!

Estrutura do código:
hello-lang
├── package-lock.json
├── package.json
├── requests.http
└── src
    └── index.jshello-lang
├── package-lock.json
├── package.json
├── requests.http
└── src
    └── index.jsimport express from 'express';
import morgan from 'morgan';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.get('/hello/pt', (req, res) => {
  res.send('Olá Mundo!');
});
 
app.get('/hello/en', (req, res) => {
  res.send('Hello World!');
});
 
app.listen(3000, () => {
  console.log('App running at http://localhost:3000');
});
 import express from 'express';
import morgan from 'morgan';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.get('/hello/pt', (req, res) => {
  res.send('Olá Mundo!');
});
 
app.get('/hello/en', (req, res) => {
  res.send('Hello World!');
});
 
app.listen(3000, () => {
  console.log('App running at http://localhost:3000');
});
 @server=http://localhost:3000
 
### Get Hello World
 
GET {{@server}}/hello/en
 
### Get Olá Mundo
 
GET {{@server}}/hello/pt
 @server=http://localhost:3000
 
### Get Hello World
 
GET {{@server}}/hello/en
 
### Get Olá Mundo
 
GET {{@server}}/hello/pt
 Morgan (HTTP request logger middleware for node.js):
$ npm install morgan$ npm install morganmorgan('tiny')
morgan(':method :url :status :res[content-length] - :response-time ms')morgan('tiny')
morgan(':method :url :status :res[content-length] - :response-time ms')$ npm start
 
> hello-lang@1.0.0 start
> node src/index.js
 
App running at http://localhost:3000
GET /hello/en 200 12 - 1.997 ms
GET /hello/pt 200 11 - 0.752 ms
GET /hello/en 200 12 - 0.381 ms$ npm start
 
> hello-lang@1.0.0 start
> node src/index.js
 
App running at http://localhost:3000
GET /hello/en 200 12 - 1.997 ms
GET /hello/pt 200 11 - 0.752 ms
GET /hello/en 200 12 - 0.381 msParâmetros de Requisição
Tipos de Parâmetros

Parâmetros:
- Query Param
- Route Param
- Body Param
Query Param

Estrutura do código:
bmi-query-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.jsbmi-query-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.jsexport function bmi(weight, height) {
  const bmi = weight / height ** 2;
 
  if (bmi < 18.5) {
    return 'Underweight';
  } else if (bmi < 25) {
    return 'Normal weight';
  } else if (bmi < 30) {
    return 'Overweight';
  } else if (bmi >= 30) {
    return 'Obesity';
  } else {
    return 'Invalid values';
  }
}
 export function bmi(weight, height) {
  const bmi = weight / height ** 2;
 
  if (bmi < 18.5) {
    return 'Underweight';
  } else if (bmi < 25) {
    return 'Normal weight';
  } else if (bmi < 30) {
    return 'Overweight';
  } else if (bmi >= 30) {
    return 'Obesity';
  } else {
    return 'Invalid values';
  }
}
 import express from 'express';
import morgan from 'morgan';
import { bmi } from './lib/bmi.js';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.get('/bmi', (req, res) => {
  const weight = Number(req.query.weight);
  const height = Number(req.query.height);
 
  const result = {
    weight,
    height,
    bmi: bmi(weight, height),
  };
 
  res.json(result);
});
 
app.listen(3000, () => {
  console.log(`App running at http://localhost:3000`);
});
 import express from 'express';
import morgan from 'morgan';
import { bmi } from './lib/bmi.js';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.get('/bmi', (req, res) => {
  const weight = Number(req.query.weight);
  const height = Number(req.query.height);
 
  const result = {
    weight,
    height,
    bmi: bmi(weight, height),
  };
 
  res.json(result);
});
 
app.listen(3000, () => {
  console.log(`App running at http://localhost:3000`);
});
 @server=http://localhost:3000
 
### Get BMI
 
GET {{@server}}/bmi?weight=100&height=1.5
 @server=http://localhost:3000
 
### Get BMI
 
GET {{@server}}/bmi?weight=100&height=1.5
 Route Param

Estrutura do código:
bmi-route-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.jsbmi-route-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.jsimport express from 'express';
import morgan from 'morgan';
import { bmi } from './lib/bmi.js';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.get('/bmi/weight/:weight/height/:height', (req, res) => {
  const weight = Number(req.params.weight);
  const height = Number(req.params.height);
 
  const result = {
    weight,
    height,
    bmi: bmi(weight, height),
  };
 
  res.json(result);
});
 
app.listen(3000, () => {
  console.log(`App running at http://localhost:3000`);
});
 import express from 'express';
import morgan from 'morgan';
import { bmi } from './lib/bmi.js';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.get('/bmi/weight/:weight/height/:height', (req, res) => {
  const weight = Number(req.params.weight);
  const height = Number(req.params.height);
 
  const result = {
    weight,
    height,
    bmi: bmi(weight, height),
  };
 
  res.json(result);
});
 
app.listen(3000, () => {
  console.log(`App running at http://localhost:3000`);
});
 @server=http://localhost:3000
 
### Get BMI
 
GET {{@server}}/bmi/weight/100/height/1.5
 @server=http://localhost:3000
 
### Get BMI
 
GET {{@server}}/bmi/weight/100/height/1.5
 Body Param

Estrutura do código:
bmi-body-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.jsbmi-body-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.jsimport express from 'express';
import morgan from 'morgan';
import { bmi } from './lib/bmi.js';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.use(express.json());
 
app.post('/bmi', (req, res) => {
  const { weight, height } = req.body;
 
  const result = {
    weight,
    height,
    bmi: bmi(weight, height),
  };
 
  res.json(result);
});
 
app.listen(3000, () => {
  console.log('App running at http://localhost:3000');
});
 import express from 'express';
import morgan from 'morgan';
import { bmi } from './lib/bmi.js';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.use(express.json());
 
app.post('/bmi', (req, res) => {
  const { weight, height } = req.body;
 
  const result = {
    weight,
    height,
    bmi: bmi(weight, height),
  };
 
  res.json(result);
});
 
app.listen(3000, () => {
  console.log('App running at http://localhost:3000');
});
 @server=http://localhost:3000
 
### Get BMI
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100,
  "height": 1.5
}
 @server=http://localhost:3000
 
### Get BMI
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100,
  "height": 1.5
}
 Resumo das Rotas
| Tipo | Node.js | HTTP | Rota | 
|---|---|---|---|
| Query Param | req.query | GET | /bmi?weight=x&height=y | 
| Route Param | req.params | GET | /bmi/weight/:weight/height/:height | 
| Body Param | req.body | POST | /bmi | 
| Rota | Dados | 
|---|---|
| /bmi?weight=x&height=y | ?weight=100&height=1.5 | 
| /bmi/weight/:weight/height/:height | /bmi/weight/100/height/1.5 | 
| /bmi | { "weight": 100, "height": 1.5 } | 
Tratamento de Erro

$ npm i express-async-errors$ npm i express-async-errorsEstrutura do código:
bmi-api
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.jsbmi-api
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.jsimport 'express-async-errors';
import express from 'express';
import morgan from 'morgan';
import { bmi } from './lib/bmi.js';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.use(express.json());
 
class HTTPError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
  }
}
 
app.post('/bmi', (req, res) => {
  const { weight, height } = req.body;
 
  if (!weight || !height) {
    throw new HTTPError('Error when passing parameters', 400);
  }
 
  const result = {
    weight,
    height,
    bmi: bmi(weight, height),
  };
 
  res.json(result);
});
 
// 404 handler
app.use((req, res, next) => {
  res.status(404).json({ message: 'Content not found!' });
});
 
// Error handler
app.use((err, req, res, next) => {
  if (err instanceof HTTPError) {
    return res.status(err.code).json({ message: err.message });
  }
 
  // console.error(err.stack);
  // next(err)
  return res.status(500).json({ message: 'Something broke!' });
});
 
app.listen(3000, () => {
  console.log('App running at http://localhost:3000');
});
 import 'express-async-errors';
import express from 'express';
import morgan from 'morgan';
import { bmi } from './lib/bmi.js';
 
const app = express();
 
app.use(morgan('tiny'));
 
app.use(express.json());
 
class HTTPError extends Error {
  constructor(message, code) {
    super(message);
    this.code = code;
  }
}
 
app.post('/bmi', (req, res) => {
  const { weight, height } = req.body;
 
  if (!weight || !height) {
    throw new HTTPError('Error when passing parameters', 400);
  }
 
  const result = {
    weight,
    height,
    bmi: bmi(weight, height),
  };
 
  res.json(result);
});
 
// 404 handler
app.use((req, res, next) => {
  res.status(404).json({ message: 'Content not found!' });
});
 
// Error handler
app.use((err, req, res, next) => {
  if (err instanceof HTTPError) {
    return res.status(err.code).json({ message: err.message });
  }
 
  // console.error(err.stack);
  // next(err)
  return res.status(500).json({ message: 'Something broke!' });
});
 
app.listen(3000, () => {
  console.log('App running at http://localhost:3000');
});
 export function bmi(weight, height) {
  if (!(weight > 0 && height > 0)) {
    throw Error('Invalid values to calculate BMI');
  }
 
  const bmi = weight / height ** 2;
 
  if (bmi < 18.5) {
    return 'Underweight';
  } else if (bmi < 25) {
    return 'Normal weight';
  } else if (bmi < 30) {
    return 'Overweight';
  } else if (bmi >= 30) {
    return 'Obesity';
  } else {
    return 'Invalid values';
  }
}
 export function bmi(weight, height) {
  if (!(weight > 0 && height > 0)) {
    throw Error('Invalid values to calculate BMI');
  }
 
  const bmi = weight / height ** 2;
 
  if (bmi < 18.5) {
    return 'Underweight';
  } else if (bmi < 25) {
    return 'Normal weight';
  } else if (bmi < 30) {
    return 'Overweight';
  } else if (bmi >= 30) {
    return 'Obesity';
  } else {
    return 'Invalid values';
  }
}
 @server=http://localhost:3000
 
### Get BMI (with params)
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100,
  "height": 1.5
}
 
### Get BMI (bad params)
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100,
  "height": -1
}
 
### Get BMI (without params)
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100
}
 
### Get BMI (without params)
 
POST {{@server}}/bmi
 
### Error 404
 
GET {{@server}}/bmi
 @server=http://localhost:3000
 
### Get BMI (with params)
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100,
  "height": 1.5
}
 
### Get BMI (bad params)
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100,
  "height": -1
}
 
### Get BMI (without params)
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100
}
 
### Get BMI (without params)
 
POST {{@server}}/bmi
 
### Error 404
 
GET {{@server}}/bmi