Introdução ao Express.js

Definição

Site Express:

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

Exemplo de Express.js

Open in GitHub

Arquivos
hello-simple
├── package.json
├── requests.http
└── src
    └── index.js
Arquivos
hello-simple
├── package.json
├── requests.http
└── src
    └── index.js

Fluxo da aplicação hello-simple:

Código da aplicação hello-simple:

/codes/expressjs/hello-simple/src/index.js
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`);
});
 
/codes/expressjs/hello-simple/src/index.js
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 -y

Adição do pacote express.js como dependência do projeto e dos scripts de execução do projeto:

$ npm install express
$ npm install express
/codes/expressjs/hello-simple/package.json
{
  "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"
  }
}
 
/codes/expressjs/hello-simple/package.json
{
  "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 start

Já a execução no modo watch (No VSCode use o NPM Scripts para executar em modo debug):

$ npm run dev
$ npm run dev

Depende 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 dev

Já para testar as requisições use o arquivo requests.http do plugin Rest Client do VSCode:

/codes/expressjs/hello-simple/requests.http
### Get Hello World
 
GET http://127.0.0.1:3000/
 
/codes/expressjs/hello-simple/requests.http
### Get Hello World
 
GET http://127.0.0.1:3000/
 

Cuidado no git para não versionar a pasta node_modules/, use o arquivo .gitignore para desconsiderar a pasta.

/codes/expressjs/hello-simple/.gitignore
node_modules
/codes/expressjs/hello-simple/.gitignore
node_modules

Rotas da Aplicação

Rotas:

Estrutura do código:

Open in GitHub

Arquivos
hello-lang
├── package-lock.json
├── package.json
├── requests.http
└── src
    └── index.js
Arquivos
hello-lang
├── package-lock.json
├── package.json
├── requests.http
└── src
    └── index.js
/codes/expressjs/hello-lang/src/index.js
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');
});
 
/codes/expressjs/hello-lang/src/index.js
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');
});
 
/codes/expressjs/hello-lang/requests.http
@server=http://localhost:3000
 
### Get Hello World
 
GET {{@server}}/hello/en
 
### Get Olá Mundo
 
GET {{@server}}/hello/pt
 
/codes/expressjs/hello-lang/requests.http
@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 morgan
morgan('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 ms

Parâmetros de Requisição

Tipos de Parâmetros

Parâmetros:

Query Param

Estrutura do código:

Open in GitHub

Arquivos
bmi-query-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.js
Arquivos
bmi-query-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.js
/codes/expressjs/bmi-query-param/src/lib/bmi.js
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';
  }
}
 
/codes/expressjs/bmi-query-param/src/lib/bmi.js
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';
  }
}
 
/codes/expressjs/bmi-query-param/src/index.js
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`);
});
 
/codes/expressjs/bmi-query-param/src/index.js
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`);
});
 
/codes/expressjs/bmi-query-param/requests.http
@server=http://localhost:3000
 
### Get BMI
 
GET {{@server}}/bmi?weight=100&height=1.5
 
/codes/expressjs/bmi-query-param/requests.http
@server=http://localhost:3000
 
### Get BMI
 
GET {{@server}}/bmi?weight=100&height=1.5
 

Route Param

Estrutura do código:

Open in GitHub

Arquivos
bmi-route-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.js
Arquivos
bmi-route-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.js
/codes/expressjs/bmi-route-param/src/index.js
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`);
});
 
/codes/expressjs/bmi-route-param/src/index.js
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`);
});
 
/codes/expressjs/bmi-route-param/requests.http
@server=http://localhost:3000
 
### Get BMI
 
GET {{@server}}/bmi/weight/100/height/1.5
 
/codes/expressjs/bmi-route-param/requests.http
@server=http://localhost:3000
 
### Get BMI
 
GET {{@server}}/bmi/weight/100/height/1.5
 

Body Param

Estrutura do código:

Open in GitHub

Arquivos
bmi-body-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.js
Arquivos
bmi-body-param
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.js
/codes/expressjs/bmi-body-param/src/index.js
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');
});
 
/codes/expressjs/bmi-body-param/src/index.js
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');
});
 
/codes/expressjs/bmi-body-param/requests.http
@server=http://localhost:3000
 
### Get BMI
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100,
  "height": 1.5
}
 
/codes/expressjs/bmi-body-param/requests.http
@server=http://localhost:3000
 
### Get BMI
 
POST {{@server}}/bmi
Content-Type: application/json
 
{
  "weight": 100,
  "height": 1.5
}
 

Resumo das Rotas

TipoNode.jsHTTPRota
Query Paramreq.queryGET/bmi?weight=x&height=y
Route Paramreq.paramsGET/bmi/weight/:weight/height/:height
Body Paramreq.bodyPOST/bmi
RotaDados
/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-errors

Estrutura do código:

Open in GitHub

Arquivos
bmi-api
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.js
Arquivos
bmi-api
├── package-lock.json
├── package.json
├── requests.http
└── src
    ├── index.js
    └── lib
        └── bmi.js
/codes/expressjs/bmi-api/src/index.js
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');
});
 
/codes/expressjs/bmi-api/src/index.js
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');
});
 
/codes/expressjs/bmi-api/src/lib/bmi.js
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';
  }
}
 
/codes/expressjs/bmi-api/src/lib/bmi.js
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';
  }
}
 
/codes/expressjs/bmi-api/requests.http
@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
 
/codes/expressjs/bmi-api/requests.http
@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
 

Referências

Editar esta página