ExpressJS - Guia Rápido
ExpressJS é uma estrutura de aplicativo da web que fornece uma API simples para construir sites, aplicativos da web e back-ends. Com ExpressJS, você não precisa se preocupar com protocolos de baixo nível, processos, etc.
O que é o Express?
O Express fornece uma interface mínima para construir nossos aplicativos. Ele nos fornece as ferramentas necessárias para construir nosso aplicativo. É flexível, pois existem vários módulos disponíveis nonpm, que pode ser conectado diretamente ao Express.
Express foi desenvolvido por TJ Holowaychuke é mantido pela fundação Node.js e vários contribuidores de código aberto.
Por que Expressar?
Ao contrário de seus concorrentes como Rails e Django, que têm uma maneira opinativa de construir aplicativos, o Express não tem "a melhor maneira" de fazer algo. É muito flexível e plugável.
Pug
Pug (anteriormente conhecido como Jade) é uma linguagem concisa para escrever modelos HTML. Isso -
- Produz HTML
- Suporta código dinâmico
- Suporta capacidade de reutilização (DRY)
É uma das linguagens de template mais populares usadas com o Express.
MongoDB e Mongoose
MongoDB é um banco de dados de documentos de código aberto projetado para facilidade de desenvolvimento e escalonamento. Este banco de dados também é usado para armazenar dados.
Mongoose é uma API cliente para node.js o que torna mais fácil acessar nosso banco de dados de nosso aplicativo Express.
Neste capítulo, aprenderemos como começar a desenvolver e usar o Express Framework. Para começar, você deve ter o Node e o npm (gerenciador de pacotes de nós) instalados. Se você ainda não os tem, vá para a configuração do nó para instalar o nó em seu sistema local. Confirme se o nó e o npm estão instalados executando os seguintes comandos em seu terminal.
node --version
npm --version
Você deve obter uma saída semelhante à seguinte.
v5.0.0
3.5.2
Agora que temos Node e npm configurar, vamos entender o que npm é e como usá-lo.
Node Package Manager (npm)
npm é o gerenciador de pacotes para o nó. O npm Registry é uma coleção pública de pacotes de código aberto para Node.js, aplicativos da web front-end, aplicativos móveis, robôs, roteadores e inúmeras outras necessidades da comunidade JavaScript. O npm nos permite acessar todos esses pacotes e instalá-los localmente. Você pode navegar pela lista de pacotes disponíveis no npm em npmJS .
Como usar o npm?
Existem duas maneiras de instalar um pacote usando npm: globalmente e localmente.
Globally- Este método é geralmente usado para instalar ferramentas de desenvolvimento e pacotes baseados em CLI. Para instalar um pacote globalmente, use o código a seguir.
npm install -g <package-name>
Locally- Este método é geralmente usado para instalar estruturas e bibliotecas. Um pacote instalado localmente pode ser usado apenas no diretório em que está instalado. Para instalar um pacote localmente, use o mesmo comando acima sem o-g bandeira.
npm install <package-name>
Sempre que criamos um projeto usando npm, precisamos fornecer um package.jsonarquivo, que contém todos os detalhes do nosso projeto. O npm facilita a configuração desse arquivo. Vamos montar nosso projeto de desenvolvimento.
Step 1 - Inicie seu terminal / cmd, crie uma nova pasta chamada hello-world e cd (criar diretório) nela -
Step 2 - Agora, para criar o arquivo package.json usando npm, use o seguinte código.
npm init
Ele solicitará as seguintes informações.
Continue pressionando enter e digite seu nome no campo “nome do autor”.
Step 3- Agora que temos nosso arquivo package.json configurado, instalaremos o Express. Para instalar o Express e adicioná-lo ao nosso arquivo package.json, use o seguinte comando -
npm install --save express
Para confirmar se o Express foi instalado corretamente, execute o código a seguir.
ls node_modules #(dir node_modules for windows)
Tip - O -save bandeira pode ser substituída pelo -Sbandeira. Este sinalizador garante que Express seja adicionado como uma dependência ao nossopackage.jsonArquivo. Isso tem uma vantagem, da próxima vez que precisarmos instalar todas as dependências do nosso projeto, podemos apenas executar o comando npm install e ele encontrará as dependências neste arquivo e as instalará para nós.
Isso é tudo de que precisamos para iniciar o desenvolvimento usando a estrutura Express. Para tornar nosso processo de desenvolvimento muito mais fácil, instalaremos uma ferramenta do npm, o nodemon. Esta ferramenta reinicia nosso servidor assim que fazemos uma alteração em qualquer um dos nossos arquivos, caso contrário, precisamos reiniciar o servidor manualmente após cada modificação de arquivo. Para instalar o nodemon, use o seguinte comando -
npm install -g nodemon
Agora você pode começar a trabalhar no Express.
Configuramos o desenvolvimento, agora é hora de começar a desenvolver nosso primeiro aplicativo usando o Express. Crie um novo arquivo chamadoindex.js e digite o seguinte nele.
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.send("Hello world!");
});
app.listen(3000);
Salve o arquivo, vá para o seu terminal e digite o seguinte.
nodemon index.js
Isso iniciará o servidor. Para testar este aplicativo, abra seu navegador e vá parahttp://localhost:3000 e uma mensagem será exibida como na imagem a seguir.
Como funciona o aplicativo?
A primeira linha importa o Express em nosso arquivo, temos acesso a ele através da variável Express. Nós o usamos para criar um aplicativo e atribuí-lo ao var app.
app.get (rota, retorno de chamada)
Esta função diz o que fazer quando um getsolicitação na rota fornecida é chamada. A função de retorno de chamada tem 2 parâmetros,request(req) e response(res). O pedidoobject(req) representa a solicitação HTTP e tem propriedades para a string de consulta da solicitação, parâmetros, corpo, cabeçalhos HTTP etc. Da mesma forma, o objeto de resposta representa a resposta HTTP que o aplicativo Express envia quando recebe uma solicitação HTTP.
res.send ()
Esta função recebe um objeto como entrada e o envia ao cliente solicitante. Aqui estamos enviando a string "Hello World!" .
app.listen (porta, [host], [backlog], [callback]])
Esta função liga e escuta as conexões no host e na porta especificados. A porta é o único parâmetro obrigatório aqui.
S.No. | Argumento e Descrição |
---|---|
1 | port Um número de porta na qual o servidor deve aceitar solicitações de entrada. |
2 | host Nome do domínio. Você precisa configurá-lo ao implantar seus aplicativos na nuvem. |
3 | backlog O número máximo de conexões pendentes enfileiradas. O padrão é 511. |
4 | callback Uma função assíncrona que é chamada quando o servidor começa a escutar as solicitações. |
Os frameworks da Web fornecem recursos como páginas HTML, scripts, imagens, etc. em diferentes rotas.
A função a seguir é usada para definir rotas em um aplicativo Express -
app.method (caminho, manipulador)
Este MÉTODO pode ser aplicado a qualquer um dos verbos HTTP - get, set, put, delete. Também existe um método alternativo, que é executado independentemente do tipo de solicitação.
Caminho é a rota em que a solicitação será executada.
Handler é uma função de retorno de chamada executada quando um tipo de solicitação correspondente é encontrado na rota relevante. Por exemplo,
var express = require('express');
var app = express();
app.get('/hello', function(req, res){
res.send("Hello World!");
});
app.listen(3000);
Se executarmos nosso aplicativo e formos para localhost:3000/hello, o servidor recebe uma solicitação get na rota "/hello", nosso aplicativo Express executa o callback função anexada a esta rota e envia "Hello World!" como a resposta.
Também podemos ter vários métodos diferentes na mesma rota. Por exemplo,
var express = require('express');
var app = express();
app.get('/hello', function(req, res){
res.send("Hello World!");
});
app.post('/hello', function(req, res){
res.send("You just called the post method at '/hello'!\n");
});
app.listen(3000);
Para testar esta solicitação, abra seu terminal e use cURL para executar a seguinte solicitação -
curl -X POST "http://localhost:3000/hello"
Um método especial, all, é fornecido pelo Express para lidar com todos os tipos de métodos http em uma rota específica usando a mesma função. Para usar este método, tente o seguinte.
app.all('/test', function(req, res){
res.send("HTTP method doesn't have any effect on this route!");
});
Este método é geralmente usado para definir middleware, que discutiremos no capítulo sobre middleware.
Roteadores
Definir rotas como acima é muito tedioso de manter. Para separar as rotas de nosso principalindex.js arquivo, vamos usar Express.Router. Crie um novo arquivo chamadothings.js e digite o seguinte nele.
var express = require('express');
var router = express.Router();
router.get('/', function(req, res){
res.send('GET route on things.');
});
router.post('/', function(req, res){
res.send('POST route on things.');
});
//export this router to use in our index.js
module.exports = router;
Agora, para usar este roteador em nosso index.js, digite o seguinte antes de app.listen chamada de função.
var express = require('Express');
var app = express();
var things = require('./things.js');
//both index.js and things.js should be in same directory
app.use('/things', things);
app.listen(3000);
o app.use chamada de função na rota '/things' anexa o thingsroteador com esta rota. Agora, quaisquer solicitações que nosso aplicativo obtiver em '/ things', serão tratadas por nosso roteador things.js. o'/'rota em things.js é na verdade um sub-roteamento de '/ things'. Visite localhost: 3000 / things / e você verá a seguinte saída.
Os roteadores são muito úteis para separar interesses e manter partes relevantes de nosso código juntas. Eles ajudam na construção de código sustentável. Você deve definir suas rotas relacionadas a uma entidade em um único arquivo e incluí-lo usando o método acima em seuindex.js Arquivo.
O método HTTP é fornecido na solicitação e especifica a operação que o cliente solicitou. A tabela a seguir lista os métodos HTTP mais usados -
S.No. | Método e Descrição |
---|---|
1 | GET O método GET solicita uma representação do recurso especificado. As solicitações usando GET devem apenas recuperar dados e não devem ter nenhum outro efeito. |
2 | POST O método POST solicita que o servidor aceite os dados incluídos na solicitação como um novo objeto / entidade do recurso identificado pelo URI. |
3 | PUT O método PUT solicita que o servidor aceite os dados incluídos na solicitação como uma modificação no objeto existente identificado pelo URI. Se não existir, o método PUT deve criar um. |
4 | DELETE O método DELETE solicita que o servidor exclua o recurso especificado. |
Esses são os métodos HTTP mais comuns. Para saber mais sobre os métodos, visitehttp://www.tutorialspoint.com/http/http_methods.htm.
Agora podemos definir rotas, mas essas são estáticas ou fixas. Para usar as rotas dinâmicas, DEVEMOS fornecer diferentes tipos de rotas. Usar rotas dinâmicas nos permite passar parâmetros e processar com base neles.
Aqui está um exemplo de uma rota dinâmica -
var express = require('express');
var app = express();
app.get('/:id', function(req, res){
res.send('The id you specified is ' + req.params.id);
});
app.listen(3000);
Para testar isso vá para http://localhost:3000/123. A seguinte resposta será exibida.
Você pode substituir '123' no URL por qualquer outra coisa e a alteração será refletida na resposta. Um exemplo mais complexo do acima é -
var express = require('express');
var app = express();
app.get('/things/:name/:id', function(req, res) {
res.send('id: ' + req.params.id + ' and name: ' + req.params.name);
});
app.listen(3000);
Para testar o código acima, vá para http://localhost:3000/things/tutorialspoint/12345.
Você pode usar o req.paramsobjeto para acessar todos os parâmetros que você passa na url. Observe que os 2 acima são caminhos diferentes. Eles nunca se sobreporão. Além disso, se você quiser executar código quando obtiver'/things' então você precisa defini-lo separadamente.
Rotas com correspondência de padrão
Você também pode usar regexpara restringir a correspondência de parâmetro de URL. Vamos supor que você precisa doidpara ser um número de 5 dígitos. Você pode usar a seguinte definição de rota -
var express = require('express');
var app = express();
app.get('/things/:id([0-9]{5})', function(req, res){
res.send('id: ' + req.params.id);
});
app.listen(3000);
Observe que isso vai only corresponder às solicitações que têm um comprimento de 5 dígitos id. Você pode usar regexes mais complexas para corresponder / validar suas rotas. Se nenhuma de suas rotas corresponder à solicitação, você receberá um"Cannot GET <your-request-route>"mensagem como resposta. Esta mensagem será substituída por uma página 404 não encontrada usando esta rota simples -
var express = require('express');
var app = express();
//Other routes here
app.get('*', function(req, res){
res.send('Sorry, this is an invalid URL.');
});
app.listen(3000);
Important - Deve ser colocado depois de todas as suas rotas, uma vez que o Express combina as rotas do início ao fim do index.js arquivo, incluindo os roteadores externos necessários.
Por exemplo, se definirmos as mesmas rotas acima, ao solicitar com um URL válido, a seguinte saída é exibida. -
Enquanto para uma solicitação de URL incorreta, a seguinte saída é exibida.
Funções de middleware são funções que têm acesso ao request object (req), a response object (res)e a próxima função de middleware no ciclo de solicitação-resposta do aplicativo. Essas funções são usadas para modificarreq e res objetos para tarefas como análise de corpos de solicitação, adição de cabeçalhos de resposta etc.
Aqui está um exemplo simples de uma função de middleware em ação -
var express = require('express');
var app = express();
//Simple request time logger
app.use(function(req, res, next){
console.log("A new request received at " + Date.now());
//This function call is very important. It tells that more processing is
//required for the current request and is in the next middleware
function/route handler.
next();
});
app.listen(3000);
O middleware acima é chamado para cada solicitação no servidor. Portanto, após cada solicitação, obteremos a seguinte mensagem no console -
A new request received at 1467267512545
Para restringi-lo a uma rota específica (e todas as suas sub-rotas), forneça essa rota como o primeiro argumento de app.use(). Por exemplo,
var express = require('express');
var app = express();
//Middleware function to log request protocol
app.use('/things', function(req, res, next){
console.log("A request for things received at " + Date.now());
next();
});
// Route handler that sends the response
app.get('/things', function(req, res){
res.send('Things');
});
app.listen(3000);
Agora, sempre que você solicitar qualquer sub-rota de '/ coisas', só então ele irá registrar a hora.
Ordem das chamadas de middleware
Uma das coisas mais importantes sobre o middleware no Express é a ordem em que são escritos / incluídos em seu arquivo; a ordem em que são executados, visto que as correspondências de rota também precisam ser consideradas.
Por exemplo, no fragmento de código a seguir, a primeira função é executada primeiro, depois o manipulador de rota e a função final. Este exemplo resume como usar o middleware antes e depois do manipulador de rota; também como um manipulador de rota pode ser usado como um middleware em si.
var express = require('express');
var app = express();
//First middleware before response is sent
app.use(function(req, res, next){
console.log("Start");
next();
});
//Route handler
app.get('/', function(req, res, next){
res.send("Middle");
next();
});
app.use('/', function(req, res){
console.log('End');
});
app.listen(3000);
Quando visitamos '/' depois de executar este código, recebemos a resposta como Middle e em nosso console -
Start
End
O diagrama a seguir resume o que aprendemos sobre middleware -
Agora que cobrimos como criar nosso próprio middleware, vamos discutir alguns dos middlewares criados pela comunidade mais comumente usados.
Middleware de Terceiros
Uma lista de middleware de terceiros para Express está disponível aqui . A seguir estão alguns dos middlewares mais comumente usados; também aprenderemos como usar / montar estes -
analisador de corpo
Isso é usado para analisar o corpo das solicitações que possuem cargas úteis anexadas a elas. Para montar o analisador de corpo, precisamos instalá-lo usandonpm install --save body-parser e para montá-lo, inclua as seguintes linhas em seu index.js -
var bodyParser = require('body-parser');
//To parse URL encoded data
app.use(bodyParser.urlencoded({ extended: false }))
//To parse json data
app.use(bodyParser.json())
Para ver todas as opções disponíveis para o analisador de corpo, visite sua página no github.
analisador de cookies
Ele analisa o cabeçalho do Cookie e preenche req.cookies com um objeto codificado por nomes de cookie. Para montar o analisador de cookies, precisamos instalá-lo usando npm install --save cookie-parser e, para montá-lo, inclua as seguintes linhas em seu index.js -
var cookieParser = require('cookie-parser');
app.use(cookieParser())
sessão expressa
Ele cria um middleware de sessão com as opções fornecidas. Discutiremos seu uso na seção Sessões.
Temos muitos outros middlewares de terceiros no ExpressJS. No entanto, discutimos apenas alguns importantes aqui.
Pug é um mecanismo de modelagem do Express. Os mecanismos de modelagem são usados para remover a confusão de nosso código de servidor com HTML, concatenando strings aos modelos HTML existentes. Pug é um motor de modelagem muito poderoso que possui uma variedade de recursos, incluindofilters, includes, inheritance, interpolation, etc. Há muito terreno a percorrer sobre isso.
Para usar o Pug com Express, precisamos instalá-lo,
npm install --save pug
Agora que o Pug está instalado, defina-o como o mecanismo de modelagem do seu aplicativo. Vocêsdon'tprecisa 'exigir' isso. Adicione o seguinte código ao seuindex.js Arquivo.
app.set('view engine', 'pug');
app.set('views','./views');
Agora crie um novo diretório chamado views. Dentro disso, crie um arquivo chamadofirst_view.puge insira os seguintes dados nele.
doctype html
html
head
title = "Hello Pug"
body
p.greetings#people Hello World!
Para executar esta página, adicione a seguinte rota ao seu aplicativo -
app.get('/first_template', function(req, res){
res.render('first_view');
});
Você obterá a saída como - Hello World!Pug converte essa marcação de aparência muito simples em html. Não precisamos acompanhar o fechamento de nossas tags, nem usar palavras-chave class e id, ao invés disso, usar '.' e'#'para defini-los. O código acima é primeiro convertido para -
<!DOCTYPE html>
<html>
<head>
<title>Hello Pug</title>
</head>
<body>
<p class = "greetings" id = "people">Hello World!</p>
</body>
</html>
Pug é capaz de fazer muito mais do que simplificar a marcação HTML.
Características importantes do Pug
Vamos agora explorar alguns recursos importantes do Pug.
Tags simples
As tags são aninhadas de acordo com sua indentação. Como no exemplo acima,<title> foi recuado dentro do <head>tag, então estava dentro dela. Mas o<body> etiqueta estava no mesmo recuo, então era uma irmã do <head> tag.
Não precisamos fechar as tags, assim que o Pug encontra a próxima tag no mesmo nível de recuo ou no nível de recuo externo, ele fecha a tag para nós.
Para colocar o texto dentro de uma tag, temos 3 métodos -
Space seperated
h1 Welcome to Pug
Piped text
div
| To insert multiline text,
| You can use the pipe operator.
Block of text
div.
But that gets tedious if you have a lot of text.
You can use "." at the end of tag to denote block of text.
To put tags inside this block, simply enter tag in a new line and
indent it accordingly.
Comentários
Pug usa a mesma sintaxe que JavaScript(//)para criar comentários. Esses comentários são convertidos em comentários html (<! - comentário ->). Por exemplo,
//This is a Pug comment
Este comentário é convertido para o seguinte.
<!--This is a Pug comment-->
Atributos
Para definir atributos, usamos uma lista de atributos separados por vírgulas, entre parênteses. Os atributos de classe e ID têm representações especiais. A linha de código a seguir cobre a definição de atributos, classes e id para uma determinada tag html.
div.container.column.main#division(width = "100", height = "100")
Esta linha de código é convertida no seguinte. -
<div class = "container column main" id = "division" width = "100" height = "100"></div>
Passando Valores para Modelos
Quando renderizamos um template Pug, podemos passar para ele um valor de nosso gerenciador de rota, que podemos então usar em nosso template. Crie um novo manipulador de rota com o seguinte.
var express = require('express');
var app = express();
app.get('/dynamic_view', function(req, res){
res.render('dynamic', {
name: "TutorialsPoint",
url:"http://www.tutorialspoint.com"
});
});
app.listen(3000);
E crie um novo arquivo de visualização no diretório de visualizações, chamado dynamic.pug, com o seguinte código -
html
head
title=name
body
h1=name
a(href = url) URL
Abra localhost: 3000 / dynamic_view em seu navegador; Você deve obter a seguinte saída -
Também podemos usar essas variáveis passadas no texto. Para inserir variáveis passadas entre o texto de uma tag, usamos#{variableName}sintaxe. Por exemplo, no exemplo acima, se quiséssemos colocar Greetings from TutorialsPoint, poderíamos ter feito o seguinte.
html
head
title = name
body
h1 Greetings from #{name}
a(href = url) URL
Este método de usar valores é chamado interpolation. O código acima exibirá a seguinte saída. -
Condicionais
Podemos usar instruções condicionais e construções de loop também.
Considere o seguinte -
Se um usuário estiver conectado, a página deve exibir "Hi, User" e se não, então o "Login/Sign Up"ligação. Para conseguir isso, podemos definir um modelo simples como -
html
head
title Simple template
body
if(user)
h1 Hi, #{user.name}
else
a(href = "/sign_up") Sign Up
Quando renderizamos isso usando nossas rotas, podemos passar um objeto como no programa a seguir -
res.render('/dynamic',{
user: {name: "Ayush", age: "20"}
});
Você receberá uma mensagem - Hi, Ayush. Mas se não passarmos nenhum objeto ou passarmos um sem chave de usuário, obteremos um link de inscrição.
Incluir e componentes
O Pug fornece uma maneira muito intuitiva de criar componentes para uma página da web. Por exemplo, se você vir um site de notícias, o cabeçalho com logotipo e categorias é sempre fixo. Em vez de copiar isso para todas as visualizações que criamos, podemos usar oincludecaracterística. O exemplo a seguir mostra como podemos usar esse recurso -
Crie 3 visualizações com o seguinte código -
HEADER.PUG
div.header.
I'm the header for this website.
CONTENT.PUG
html
head
title Simple template
body
include ./header.pug
h3 I'm the main content
include ./footer.pug
FOOTER.PUG
div.footer.
I'm the footer for this website.
Crie uma rota para isso da seguinte maneira -
var express = require('express');
var app = express();
app.get('/components', function(req, res){
res.render('content');
});
app.listen(3000);
Vá para localhost: 3000 / components, você receberá a seguinte saída -
include também pode ser usado para incluir texto simples, css e JavaScript.
Existem muitos outros recursos do Pug. Mas esses estão fora do escopo deste tutorial. Você pode explorar mais o Pug em Pug .
Os arquivos estáticos são arquivos que os clientes baixam quando estão no servidor. Crie um novo diretório,public. Express, por padrão não permite que você forneça arquivos estáticos. Você precisa habilitá-lo usando o seguinte middleware integrado.
app.use(express.static('public'));
Note - O Express procura os arquivos relativos ao diretório estático, portanto, o nome do diretório estático não faz parte da URL.
Observe que a rota raiz agora está definida para seu diretório público, portanto, todos os arquivos estáticos que você carregar serão considerados públicos como raiz. Para testar se está funcionando bem, adicione qualquer arquivo de imagem em seu novopublic dir e mude seu nome para "testimage.jpg". Em suas visualizações, crie uma nova visualização e inclua este arquivo como -
html
head
body
h3 Testing static file serving:
img(src = "/testimage.jpg", alt = "Testing Image
Você deve obter a seguinte saída -
Vários diretórios estáticos
Também podemos definir vários diretórios de ativos estáticos usando o seguinte programa -
var express = require('express');
var app = express();
app.use(express.static('public'));
app.use(express.static('images'));
app.listen(3000);
Prefixo de caminho virtual
Também podemos fornecer um prefixo de caminho para servir arquivos estáticos. Por exemplo, se você deseja fornecer um prefixo de caminho como'/static', você precisa incluir o seguinte código em seu index.js arquivo -
var express = require('express');
var app = express();
app.use('/static', express.static('public'));
app.listen(3000);
Agora, sempre que você precisar incluir um arquivo, por exemplo, um arquivo de script chamado main.js residente em seu diretório público, use a seguinte tag de script -
<script src = "/static/main.js" />
Essa técnica pode ser útil ao fornecer vários diretórios como arquivos estáticos. Esses prefixos podem ajudar a distinguir entre vários diretórios.
Os formulários são parte integrante da web. Quase todos os sites que visitamos nos oferecem formulários que enviam ou buscam algumas informações para nós. Para começar com os formulários, primeiro instalaremos o middleware body-parser (para analisar JSON e dados codificados por url) e multer (para analisar dados multipart / form).
Para instalar o analisador de corpo e multer , vá para o seu terminal e use -
npm install --save body-parser multer
Substitua seu index.js conteúdo do arquivo com o seguinte código -
var express = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var app = express();
app.get('/', function(req, res){
res.render('form');
});
app.set('view engine', 'pug');
app.set('views', './views');
// for parsing application/json
app.use(bodyParser.json());
// for parsing application/xwww-
app.use(bodyParser.urlencoded({ extended: true }));
//form-urlencoded
// for parsing multipart/form-data
app.use(upload.array());
app.use(express.static('public'));
app.post('/', function(req, res){
console.log(req.body);
res.send("recieved your request!");
});
app.listen(3000);
Depois de importar o analisador de corpo e o multer, usaremos o body-parser para analisar solicitações de cabeçalho json e x-www-form-urlencoded, enquanto usaremos multer para analisar multipart / form-data.
Vamos criar um formulário html para testar isso. Crie uma nova vista chamadaform.pug com o seguinte código -
html
html
head
title Form Tester
body
form(action = "/", method = "POST")
div
label(for = "say") Say:
input(name = "say" value = "Hi")
br
div
label(for = "to") To:
input(name = "to" value = "Express forms")
br
button(type = "submit") Send my greetings
Execute o seu servidor usando o seguinte.
nodemon index.js
Agora vá para localhost: 3000 / e preencha o formulário como quiser e envie. A seguinte resposta será exibida -
Dê uma olhada em seu console; ele mostrará o corpo da sua solicitação como um objeto JavaScript, como na imagem a seguir -
o req.bodyobjeto contém seu corpo de solicitação analisado. Para usar os campos desse objeto, basta usá-los como objetos JS normais.
Esta é a forma mais recomendada de enviar uma solicitação. Existem muitas outras maneiras, mas essas são irrelevantes para abordar aqui, porque nosso aplicativo Express tratará todas essas solicitações da mesma maneira. Para ler mais sobre as diferentes maneiras de fazer uma solicitação, dê uma olhada nesta página.
Continuamos recebendo solicitações, mas acabamos não armazenando em lugar nenhum. Precisamos de um banco de dados para armazenar os dados. Para isso, faremos uso do banco de dados NoSQL chamadoMongoDB.
Para instalar e ler sobre o Mongo, siga este link.
Para usar o Mongo com o Express, precisamos de uma API cliente para o nó. Existem várias opções para nós, mas para este tutorial, vamos nos limitar ao mangusto . Mongoose é usado paradocument Modelingno Node para MongoDB. Para modelagem de documentos, criamos umModel (muito parecido com um class na programação orientada a documentos), e então produzimos documents usando este modelo (como criamos documents of a classem OOP). Todo o nosso processamento será feito nestes "documentos", então finalmente, iremos escrever estes documentos em nosso banco de dados.
Configurando o Mongoose
Agora que você instalou o Mongo, vamos instalar o Mongoose, da mesma forma que instalamos nossos outros pacotes de nós -
npm install --save mongoose
Antes de começarmos a usar o mongoose, temos que criar um banco de dados usando o shell Mongo. Para criar um novo banco de dados, abra seu terminal e digite "mongo". Um shell Mongo será iniciado, digite o seguinte código -
use my_db
Um novo banco de dados será criado para você. Sempre que você abrir o shell do mongo, o padrão será "test" db e você terá que mudar para seu banco de dados usando o mesmo comando acima.
Para usar o Mongoose, vamos exigi-lo em nosso index.js arquivo e, em seguida, conecte-se ao mongodb serviço em execução mongodb://localhost.
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');
Agora que nosso aplicativo está conectado ao nosso banco de dados, vamos criar um novo modelo. Este modelo funcionará como uma coleção em nosso banco de dados. Para criar um novo modelo, use o seguinte código, antes de definir qualquer rota -
var personSchema = mongoose.Schema({
name: String,
age: Number,
nationality: String
});
var Person = mongoose.model("Person", personSchema);
O código acima define o esquema para uma pessoa e é usado para criar um Modo Mongoose Person.
Salvando documentos
Agora, vamos criar um novo formulário html; este formulário irá ajudá-lo a obter os detalhes de uma pessoa e salvá-los em nosso banco de dados. Para criar o formulário, crie um novo arquivo de visualização chamadoperson.pug no diretório de visualizações com o seguinte conteúdo -
html
head
title Person
body
form(action = "/person", method = "POST")
div
label(for = "name") Name:
input(name = "name")
br
div
label(for = "age") Age:
input(name = "age")
br
div
label(for = "nationality") Nationality:
input(name = "nationality")
br
button(type = "submit") Create new person
Adicione também um new get route dentro index.js para processar este documento -
app.get('/person', function(req, res){
res.render('person');
});
Vamos para "localhost:3000/person"para verificar se o formulário está exibindo a saída correta. Observe que esta é apenas a IU, ainda não está funcionando. A captura de tela a seguir mostra como o formulário é exibido -
Vamos agora definir um gerenciador de pós-rota em '/person' que vai lidar com este pedido
app.post('/person', function(req, res){
var personInfo = req.body; //Get the parsed information
if(!personInfo.name || !personInfo.age || !personInfo.nationality){
res.render('show_message', {
message: "Sorry, you provided worng info", type: "error"});
} else {
var newPerson = new Person({
name: personInfo.name,
age: personInfo.age,
nationality: personInfo.nationality
});
newPerson.save(function(err, Person){
if(err)
res.render('show_message', {message: "Database error", type: "error"});
else
res.render('show_message', {
message: "New person added", type: "success", person: personInfo});
});
}
});
No código acima, se recebermos algum campo vazio ou não recebermos nenhum campo, enviaremos uma resposta de erro. Mas se recebermos um documento bem formado, então criamos umnewPerson documento do modelo Person e salvá-lo em nosso banco de dados usando o newPerson.save()função. Isso é definido no Mongoose e aceita um retorno de chamada como argumento. Este retorno de chamada tem 2 argumentos - erro e resposta. Esses argumentos irão renderizar oshow_message Visão.
Para mostrar a resposta dessa rota, também precisaremos criar um show_messageVisão. Crie uma nova visualização com o seguinte código -
html
head
title Person
body
if(type == "error")
h3(style = "color:red") #{message}
else
h3 New person,
name: #{person.name},
age: #{person.age} and
nationality: #{person.nationality} added!
Receberemos a seguinte resposta ao enviar com sucesso o form(show_message.pug) -
Agora temos uma interface para criar persons.
Recuperando Documentos
O Mongoose fornece muitas funções para recuperar documentos, vamos nos concentrar em 3 delas. Todas essas funções também recebem um retorno de chamada como o último parâmetro e, assim como a função salvar, seus argumentos são erro e resposta. As três funções são as seguintes -
Model.find (condições, retorno de chamada)
Esta função encontra todos os documentos correspondentes aos campos no objeto de condições. Os mesmos operadores usados no Mongo também funcionam no mangusto. Por exemplo,
Person.find(function(err, response){
console.log(response);
});
Isso irá buscar todos os documentos da coleção da pessoa.
Person.find({name: "Ayush", age: 20},
function(err, response){
console.log(response);
});
Isso irá buscar todos os documentos onde o nome do campo é "Ayush" e a idade é 20.
Também podemos fornecer a projeção de que precisamos, ou seja, os campos de que precisamos. Por exemplo, se quisermos apenas onames de pessoas cujo nationalityé "indiano" , usamos -
Person.find({nationality: "Indian"}, "name", function(err, response){
console.log(response);
});
Model.findOne (condições, retorno de chamada)
Esta função sempre busca um único documento mais relevante. Tem exatamente os mesmos argumentos queModel.find().
Model.findById (id, callback)
Esta função leva no _id(definido por mongo) como o primeiro argumento, uma string de projeção opcional e um retorno de chamada para lidar com a resposta. Por exemplo,
Person.findById("507f1f77bcf86cd799439011", function(err, response){
console.log(response);
});
Vamos agora criar uma rota para visualizar todos os registros de pessoas -
var express = require('express');
var app = express();
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');
var personSchema = mongoose.Schema({
name: String,
age: Number,
nationality: String
});
var Person = mongoose.model("Person", personSchema);
app.get('/people', function(req, res){
Person.find(function(err, response){
res.json(response);
});
});
app.listen(3000);
Atualizando Documentos
O Mongoose oferece 3 funções para atualizar documentos. As funções são descritas abaixo -
Model.update (condição, atualizações, retorno de chamada)
Essa função pega uma condição e atualiza um objeto como entrada e aplica as alterações a todos os documentos que correspondem às condições na coleção. Por exemplo, o código a seguir atualizará a nacionalidade "American" em todos os documentos pessoais -
Person.update({age: 25}, {nationality: "American"}, function(err, response){
console.log(response);
});
Model.findOneAndUpdate (condição, atualizações, retorno de chamada)
Ele encontra um documento com base na consulta e o atualiza de acordo com o segundo argumento. Também leva um retorno de chamada como último argumento. Vamos realizar o seguinte exemplo para entender a função
Person.findOneAndUpdate({name: "Ayush"}, {age: 40}, function(err, response) {
console.log(response);
});
Model.findByIdAndUpdate (id, updates, callback)
Esta função atualiza um único documento identificado por seu id. Por exemplo,
Person.findByIdAndUpdate("507f1f77bcf86cd799439011", {name: "James"},
function(err, response){
console.log(response);
});
Vamos agora criar uma rota para atualizar as pessoas. Este será umPUT rota com o id como parâmetro e detalhes na carga útil.
var express = require('express');
var app = express();
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');
var personSchema = mongoose.Schema({
name: String,
age: Number,
nationality: String
});
var Person = mongoose.model("Person", personSchema);
app.put('/people/:id', function(req, res){
Person.findByIdAndUpdate(req.params.id, req.body, function(err, response){
if(err) res.json({message: "Error in updating person with id " + req.params.id});
res.json(response);
});
});
app.listen(3000);
Para testar esta rota, digite o seguinte em seu terminal (substitua o id por um id do seu criado people) -
curl -X PUT --data "name = James&age = 20&nationality = American
"http://localhost:3000/people/507f1f77bcf86cd799439011
Isso atualizará o documento associado ao id fornecido na rota com os detalhes acima.
Apagando Documentos
Nós cobrimos Create, Read e Update, agora veremos como o Mongoose pode ser usado para Deletedocumentos. Temos 3 funções aqui, exatamente como atualizar.
Model.remove (condição, [retorno de chamada])
Esta função recebe um objeto de condição como entrada e remove todos os documentos que atendem às condições. Por exemplo, se precisarmos remover todas as pessoas com 20 anos, use a seguinte sintaxe -
Person.remove({age:20});
Model.findOneAndRemove (condição, [retorno de chamada])
Esta função remove um single, documento mais relevante de acordo com o objeto de condições. Vamos executar o código a seguir para entender o mesmo.
Person.findOneAndRemove({name: "Ayush"});
Model.findByIdAndRemove (id, [callback])
Esta função remove um único documento identificado por seu id. Por exemplo,
Person.findByIdAndRemove("507f1f77bcf86cd799439011");
Vamos agora criar uma rota para deletar pessoas de nosso banco de dados.
var express = require('express');
var app = express();
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/my_db');
var personSchema = mongoose.Schema({
name: String,
age: Number,
nationality: String
});
var Person = mongoose.model("Person", personSchema);
app.delete('/people/:id', function(req, res){
Person.findByIdAndRemove(req.params.id, function(err, response){
if(err) res.json({message: "Error in deleting record id " + req.params.id});
else res.json({message: "Person with id " + req.params.id + " removed."});
});
});
app.listen(3000);
Para verificar a saída, use o seguinte comando curl -
curl -X DELETE http://localhost:3000/people/507f1f77bcf86cd799439011
Isso removerá a pessoa com o id fornecido, produzindo a seguinte mensagem -
{message: "Person with id 507f1f77bcf86cd799439011 removed."}
Isso conclui como podemos criar aplicativos CRUD simples usando MongoDB, Mongoose e Express. Para explorar mais o Mongoose, leia os documentos da API.
Cookies são arquivos / dados simples e pequenos que são enviados ao cliente com uma solicitação do servidor e armazenados no lado do cliente. Cada vez que o usuário carrega o site de volta, este cookie é enviado com a solicitação. Isso nos ajuda a acompanhar as ações do usuário.
A seguir estão os diversos usos dos cookies HTTP -
- Gerenciamento de sessão
- Personalização (sistemas de recomendação)
- Rastreamento de usuário
Para usar cookies com o Express, precisamos do middleware analisador de cookies. Para instalá-lo, use o seguinte código -
npm install --save cookie-parser
Agora, para usar cookies com Express, vamos exigir o cookie-parser. O analisador de cookies é um middleware que analisa cookies anexados ao objeto de solicitação do cliente . Para usá-lo, vamos exigi-lo em nossoindex.jsArquivo; isso pode ser usado da mesma maneira que usamos outro middleware. Aqui, usaremos o seguinte código.
var cookieParser = require('cookie-parser');
app.use(cookieParser());
O analisador de cookies analisa o cabeçalho do cookie e preenche req.cookiescom um objeto codificado pelos nomes dos cookies. Para definir um novo cookie, vamos definir uma nova rota em seu aplicativo Express como -
var express = require('express');
var app = express();
app.get('/', function(req, res){
res.cookie('name', 'express').send('cookie set'); //Sets name = express
});
app.listen(3000);
Para verificar se o seu cookie está configurado ou não, basta acessar o navegador, iniciar o console e inserir -
console.log(document.cookie);
Você obterá a saída como (você pode ter mais cookies definidos, talvez devido a extensões em seu navegador) -
"name = express"
O navegador também envia cookies de volta toda vez que consulta o servidor. Para visualizar os cookies do seu servidor, no console do servidor em uma rota, adicione o seguinte código a essa rota.
console.log('Cookies: ', req.cookies);
Na próxima vez que você enviar uma solicitação para esta rota, receberá a seguinte saída.
Cookies: { name: 'express' }
Adicionando Cookies com Tempo de Expiração
Você pode adicionar cookies que expiram. Para adicionar um cookie que expira, basta passar um objeto com a propriedade 'expirar' definida para a hora em que deseja que ele expire. Por exemplo,
//Expires after 360000 ms from the time it is set.
res.cookie(name, 'value', {expire: 360000 + Date.now()});
Outra maneira de definir o tempo de expiração é usando 'maxAge'propriedade. Usando essa propriedade, podemos fornecer o tempo relativo em vez do tempo absoluto. A seguir está um exemplo desse método.
//This cookie also expires after 360000 ms from the time it is set.
res.cookie(name, 'value', {maxAge: 360000});
Excluindo Cookies Existentes
Para excluir um cookie, use a função clearCookie. Por exemplo, se você precisar limpar um cookie chamadofoo, use o código a seguir.
var express = require('express');
var app = express();
app.get('/clear_cookie_foo', function(req, res){
res.clearCookie('foo');
res.send('cookie foo cleared');
});
app.listen(3000);
No próximo capítulo, veremos como usar cookies para gerenciar sessões.
HTTP não tem estado; para associar uma solicitação a qualquer outra solicitação, você precisa de uma maneira de armazenar os dados do usuário entre as solicitações HTTP. Cookies e parâmetros de URL são formas adequadas de transporte de dados entre o cliente e o servidor. Mas eles são legíveis e do lado do cliente. As sessões resolvem exatamente esse problema. Você atribui um ID ao cliente e ele faz todas as solicitações adicionais usando esse ID. As informações associadas ao cliente são armazenadas no servidor vinculado a este ID.
Precisaremos da sessão Express , portanto instale-a usando o código a seguir.
npm install --save express-session
Vamos colocar o session e cookie-parsermiddleware instalado. Neste exemplo, usaremos o armazenamento padrão para armazenar sessões, ou seja, MemoryStore. Nunca use isso em ambientes de produção. O middleware de sessão lida com todas as coisas para nós, ou seja, criar a sessão, definir o cookie de sessão e criar o objeto de sessão emreq objeto.
Sempre que voltarmos a fazer um pedido ao mesmo cliente, teremos as suas informações de sessão armazenadas connosco (visto que o servidor não foi reiniciado). Podemos adicionar mais propriedades ao objeto de sessão. No exemplo a seguir, criaremos um contador de visualizações para um cliente.
var express = require('express');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var app = express();
app.use(cookieParser());
app.use(session({secret: "Shh, its a secret!"}));
app.get('/', function(req, res){
if(req.session.page_views){
req.session.page_views++;
res.send("You visited this page " + req.session.page_views + " times");
} else {
req.session.page_views = 1;
res.send("Welcome to this page for the first time!");
}
});
app.listen(3000);
O que o código acima faz é, quando um usuário visita o site, ele cria uma nova sessão para o usuário e atribui a ele um cookie. Da próxima vez que o usuário vier, o cookie será verificado e opage_view a variável da sessão é atualizada de acordo.
Agora, se você executar o aplicativo e for para localhost:3000, a seguinte saída será exibida.
Se você revisitar a página, o contador de páginas aumentará. A página da captura de tela a seguir foi atualizada 42 vezes.
A autenticação é um processo no qual as credenciais fornecidas são comparadas àquelas armazenadas em um banco de dados de informações de usuários autorizados em um sistema operacional local ou em um servidor de autenticação. Se as credenciais corresponderem, o processo será concluído e o usuário receberá autorização de acesso.
Para criarmos um sistema de autenticação, precisaremos criar uma página de inscrição e um armazenamento de senha de usuário. O código a seguir cria uma conta para nós e a armazena na memória. Isso é apenas para fins de demonstração; é recomendável que um armazenamento persistente (banco de dados ou arquivos) seja sempre usado para armazenar informações do usuário.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var session = require('express-session');
var cookieParser = require('cookie-parser');
app.set('view engine', 'pug');
app.set('views','./views');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.array());
app.use(cookieParser());
app.use(session({secret: "Your secret key"}));
var Users = [];
app.get('/signup', function(req, res){
res.render('signup');
});
app.post('/signup', function(req, res){
if(!req.body.id || !req.body.password){
res.status("400");
res.send("Invalid details!");
} else {
Users.filter(function(user){
if(user.id === req.body.id){
res.render('signup', {
message: "User Already Exists! Login or choose another user id"});
}
});
var newUser = {id: req.body.id, password: req.body.password};
Users.push(newUser);
req.session.user = newUser;
res.redirect('/protected_page');
}
});
app.listen(3000);
Agora, para o formulário de inscrição, crie uma nova visualização chamada signup.jade.
SIGNUP.JADE
html
head
title Signup
body
if(message)
h4 #{message}
form(action = "/signup" method = "POST")
input(name = "id" type = "text" required placeholder = "User ID")
input(name = "password" type = "password" required placeholder = "Password")
button(type = "Submit") Sign me up!
Verifique se esta página carrega visitando localhost: 3000 / signup.
Definimos o atributo obrigatório para ambos os campos, portanto, os navegadores habilitados para HTML5 não nos permitirão enviar este formulário até que forneçamos o id e a senha. Se alguém tentar se registrar usando uma solicitação curl sem uma ID de usuário ou senha, um erro será exibido. Crie um novo arquivo chamadoprotected_page.pug em visualizações com o seguinte conteúdo -
html
head
title Protected page
body
div Hey #{id}, How are you doing today?
div Want to log out?
div Logout
Esta página só deve ser visível se o usuário acabou de se cadastrar ou logar. Vamos agora definir sua rota e também as rotas de login e logout -
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var session = require('express-session');
var cookieParser = require('cookie-parser');
app.set('view engine', 'pug');
app.set('views','./views');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.array());
app.use(cookieParser());
app.use(session({secret: "Your secret key"}));
var Users = [];
app.get('/signup', function(req, res){
res.render('signup');
});
app.post('/signup', function(req, res){
if(!req.body.id || !req.body.password){
res.status("400");
res.send("Invalid details!");
} else {
Users.filter(function(user){
if(user.id === req.body.id){
res.render('signup', {
message: "User Already Exists! Login or choose another user id"});
}
});
var newUser = {id: req.body.id, password: req.body.password};
Users.push(newUser);
req.session.user = newUser;
res.redirect('/protected_page');
}
});
function checkSignIn(req, res){
if(req.session.user){
next(); //If session exists, proceed to page
} else {
var err = new Error("Not logged in!");
console.log(req.session.user);
next(err); //Error, trying to access unauthorized page!
}
}
app.get('/protected_page', checkSignIn, function(req, res){
res.render('protected_page', {id: req.session.user.id})
});
app.get('/login', function(req, res){
res.render('login');
});
app.post('/login', function(req, res){
console.log(Users);
if(!req.body.id || !req.body.password){
res.render('login', {message: "Please enter both id and password"});
} else {
Users.filter(function(user){
if(user.id === req.body.id && user.password === req.body.password){
req.session.user = user;
res.redirect('/protected_page');
}
});
res.render('login', {message: "Invalid credentials!"});
}
});
app.get('/logout', function(req, res){
req.session.destroy(function(){
console.log("user logged out.")
});
res.redirect('/login');
});
app.use('/protected_page', function(err, req, res, next){
console.log(err);
//User should be authenticated! Redirect him to log in.
res.redirect('/login');
});
app.listen(3000);
Criamos uma função de middleware checkSignIn para verificar se o usuário está conectado .protected_pageusa esta função. Para desconectar o usuário, destruímos a sessão.
Vamos agora criar a página de login. Nomeie a vista comologin.pug e insira o conteúdo -
html
head
title Signup
body
if(message)
h4 #{message}
form(action = "/login" method = "POST")
input(name = "id" type = "text" required placeholder = "User ID")
input(name = "password" type = "password" required placeholder = "Password")
button(type = "Submit") Log in
Nosso aplicativo de autenticação simples agora está completo; vamos agora testar o aplicativo. Execute o aplicativo usando nodemon index.js e prossiga para localhost: 3000 / signup.
Digite um nome de usuário e uma senha e clique em inscrever-se. Você será redirecionado para oprotected_page se os detalhes são válidos / únicos -
Agora saia do aplicativo. Isso nos redirecionará para a página de login -
Esta rota é protegida de forma que se uma pessoa não autenticada tentar visitá-la, ela será redirecionada para nossa página de login. Tudo se resumia à autenticação básica do usuário. É sempre recomendável usar um sistema de sessão persistente e usar hashes para transporte de senha. Existem maneiras muito melhores de autenticar usuários agora, aproveitando tokens JSON.
Uma API é sempre necessária para criar aplicativos móveis, aplicativos de página única, usar chamadas AJAX e fornecer dados aos clientes. Um estilo de arquitetura popular de como estruturar e nomear essas APIs e os terminais é chamadoREST(Representational Transfer State). HTTP 1.1foi projetado tendo os princípios REST em mente. REST foi introduzido porRoy Fielding em 2000 em seu Paper Fielding Dissertations.
URIs e métodos RESTful nos fornecem quase todas as informações de que precisamos para processar uma solicitação. A tabela abaixo resume como os vários verbos devem ser usados e como os URIs devem ser nomeados. Estaremos criando uma API de filmes no final; vamos agora discutir como ele será estruturado.
Método | URI | Detalhes | Função |
---|---|---|---|
PEGUE | /filmes | Seguro, encaixável | Obtém a lista de todos os filmes e seus detalhes |
PEGUE | / movies / 1234 | Seguro, encaixável | Obtém os detalhes da identificação do filme 1234 |
POSTAR | /filmes | N / D | Cria um novo filme com os detalhes fornecidos. A resposta contém o URI para este recurso recém-criado. |
COLOCAR | / movies / 1234 | Idempotente | Modifica a identificação do filme 1234 (cria uma se ainda não existir). A resposta contém o URI para este recurso recém-criado. |
EXCLUIR | / movies / 1234 | Idempotente | A identificação do filme 1234 deve ser excluída, se existir. A resposta deve conter o status da solicitação. |
DELETE ou PUT | /filmes | Inválido | Deve ser inválido. DELETE e PUT deve especificar em qual recurso estão trabalhando. |
Vamos agora criar essa API no Express. Usaremos JSON como nosso formato de transporte de dados, pois é fácil trabalhar com JavaScript e tem outros benefícios. Substitua seuindex.js arquivo com o movies.js arquivo como no programa a seguir.
index.js
var express = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var app = express();
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(upload.array());
//Require the Router we defined in movies.js
var movies = require('./movies.js');
//Use the Router on the sub route /movies
app.use('/movies', movies);
app.listen(3000);
Agora que nosso aplicativo está configurado, vamos nos concentrar na criação da API.
Comece configurando o arquivo movies.js. Não estamos usando um banco de dados para armazenar os filmes, mas sim na memória; portanto, sempre que o servidor for reiniciado, os filmes adicionados por nós desaparecerão. Isso pode ser facilmente imitado usando um banco de dados ou um arquivo (usando o módulo node fs).
Depois de importar o Express, crie um roteador e exporte-o usando module.exports -
var express = require('express');
var router = express.Router();
var movies = [
{id: 101, name: "Fight Club", year: 1999, rating: 8.1},
{id: 102, name: "Inception", year: 2010, rating: 8.7},
{id: 103, name: "The Dark Knight", year: 2008, rating: 9},
{id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}
];
//Routes will go here
module.exports = router;
OBTER rotas
Vamos definir a rota GET para obter todos os filmes -
router.get('/', function(req, res){
res.json(movies);
});
Para testar se está funcionando bem, execute seu aplicativo, abra o terminal e digite -
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET
localhost:3000/movies
A seguinte resposta será exibida -
[{"id":101,"name":"Fight Club","year":1999,"rating":8.1},
{"id":102,"name":"Inception","year":2010,"rating":8.7},
{"id":103,"name":"The Dark Knight","year":2008,"rating":9},
{"id":104,"name":"12 Angry Men","year":1957,"rating":8.9}]
Temos uma rota para obter todos os filmes. Vamos agora criar uma rota para obter um filme específico por seu id.
router.get('/:id([0-9]{3,})', function(req, res){
var currMovie = movies.filter(function(movie){
if(movie.id == req.params.id){
return true;
}
});
if(currMovie.length == 1){
res.json(currMovie[0])
} else {
res.status(404);//Set status to 404 as movie was not found
res.json({message: "Not Found"});
}
});
Isso nos dará os filmes de acordo com a id que fornecemos. Para verificar a saída, use o seguinte comando em seu terminal -
curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X GET
localhost:3000/movies/101
Você obterá a seguinte resposta -
{"id":101,"name":"Fight Club","year":1999,"rating":8.1}
Se você visitar uma rota inválida, produzirá um cannot GET error enquanto se você visitar uma rota válida com um id que não existe, ele produzirá um erro 404.
Concluímos as rotas GET, vamos agora passar para o POST rota.
POST rota
Use a seguinte rota para lidar com o POSTed dados -
router.post('/', function(req, res){
//Check if all fields are provided and are valid:
if(!req.body.name ||
!req.body.year.toString().match(/^[0-9]{4}$/g) || !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){
res.status(400);
res.json({message: "Bad Request"});
} else {
var newId = movies[movies.length-1].id+1;
movies.push({
id: newId,
name: req.body.name,
year: req.body.year,
rating: req.body.rating
});
res.json({message: "New movie created.", location: "/movies/" + newId});
}
});
Isso criará um novo filme e o armazenará na variável movies. Para verificar esta rota, digite o seguinte código em seu terminal -
curl -X POST --data "name = Toy%20story&year = 1995&rating = 8.5" http://localhost:3000/movies
A seguinte resposta será exibida -
{"message":"New movie created.","location":"/movies/105"}
Para testar se isso foi adicionado ao objeto movies, execute a solicitação get para /movies/105novamente. A seguinte resposta será exibida -
{"id":105,"name":"Toy story","year":"1995","rating":"8.5"}
Vamos prosseguir para criar as rotas PUT e DELETE.
PUT rota
A rota PUT é quase igual à rota POST. Estaremos especificando o id do objeto que será atualizado / criado. Crie a rota da seguinte maneira.
router.put('/:id', function(req, res){
//Check if all fields are provided and are valid:
if(!req.body.name ||
!req.body.year.toString().match(/^[0-9]{4}$/g) || !req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) ||
!req.params.id.toString().match(/^[0-9]{3,}$/g)){
res.status(400);
res.json({message: "Bad Request"});
} else {
//Gets us the index of movie with given id.
var updateIndex = movies.map(function(movie){
return movie.id;
}).indexOf(parseInt(req.params.id));
if(updateIndex === -1){
//Movie not found, create new
movies.push({
id: req.params.id,
name: req.body.name,
year: req.body.year,
rating: req.body.rating
});
res.json({message: "New movie created.", location: "/movies/" + req.params.id});
} else {
//Update existing movie
movies[updateIndex] = {
id: req.params.id,
name: req.body.name,
year: req.body.year,
rating: req.body.rating
};
res.json({message: "Movie id " + req.params.id + " updated.",
location: "/movies/" + req.params.id});
}
}
});
Esta rota executará a função especificada na tabela acima. Ele atualizará o objeto com novos detalhes, se existir. Se não existir, ele criará um novo objeto. Para verificar a rota, use o seguinte comando curl. Isso irá atualizar um filme existente. Para criar um novo filme, basta alterar o id para um id não existente.
curl -X PUT --data "name = Toy%20story&year = 1995&rating = 8.5"
http://localhost:3000/movies/101
Response
{"message":"Movie id 101 updated.","location":"/movies/101"}
DELETE rota
Use o código a seguir para criar uma rota de exclusão. -
router.delete('/:id', function(req, res){
var removeIndex = movies.map(function(movie){
return movie.id;
}).indexOf(req.params.id); //Gets us the index of movie with given id.
if(removeIndex === -1){
res.json({message: "Not found"});
} else {
movies.splice(removeIndex, 1);
res.send({message: "Movie id " + req.params.id + " removed."});
}
});
Verifique a rota da mesma forma que verificamos as outras rotas. Na exclusão bem-sucedida (por exemplo, id 105), você obterá a seguinte saída -
{message: "Movie id 105 removed."}
Finalmente, nosso movies.js arquivo terá a seguinte aparência.
var express = require('express');
var router = express.Router();
var movies = [
{id: 101, name: "Fight Club", year: 1999, rating: 8.1},
{id: 102, name: "Inception", year: 2010, rating: 8.7},
{id: 103, name: "The Dark Knight", year: 2008, rating: 9},
{id: 104, name: "12 Angry Men", year: 1957, rating: 8.9}
];
router.get('/:id([0-9]{3,})', function(req, res){
var currMovie = movies.filter(function(movie){
if(movie.id == req.params.id){
return true;
}
});
if(currMovie.length == 1){
res.json(currMovie[0])
} else {
res.status(404); //Set status to 404 as movie was not found
res.json({message: "Not Found"});
}
});
router.post('/', function(req, res){
//Check if all fields are provided and are valid:
if(!req.body.name ||
!req.body.year.toString().match(/^[0-9]{4}$/g) ||
!req.body.rating.toString().match(/^[0-9]\.[0-9]$/g)){ res.status(400); res.json({message: "Bad Request"}); } else { var newId = movies[movies.length-1].id+1; movies.push({ id: newId, name: req.body.name, year: req.body.year, rating: req.body.rating }); res.json({message: "New movie created.", location: "/movies/" + newId}); } }); router.put('/:id', function(req, res) { //Check if all fields are provided and are valid: if(!req.body.name || !req.body.year.toString().match(/^[0-9]{4}$/g) ||
!req.body.rating.toString().match(/^[0-9]\.[0-9]$/g) || !req.params.id.toString().match(/^[0-9]{3,}$/g)){
res.status(400);
res.json({message: "Bad Request"});
} else {
//Gets us the index of movie with given id.
var updateIndex = movies.map(function(movie){
return movie.id;
}).indexOf(parseInt(req.params.id));
if(updateIndex === -1){
//Movie not found, create new
movies.push({
id: req.params.id,
name: req.body.name,
year: req.body.year,
rating: req.body.rating
});
res.json({
message: "New movie created.", location: "/movies/" + req.params.id});
} else {
//Update existing movie
movies[updateIndex] = {
id: req.params.id,
name: req.body.name,
year: req.body.year,
rating: req.body.rating
};
res.json({message: "Movie id " + req.params.id + " updated.",
location: "/movies/" + req.params.id});
}
}
});
router.delete('/:id', function(req, res){
var removeIndex = movies.map(function(movie){
return movie.id;
}).indexOf(req.params.id); //Gets us the index of movie with given id.
if(removeIndex === -1){
res.json({message: "Not found"});
} else {
movies.splice(removeIndex, 1);
res.send({message: "Movie id " + req.params.id + " removed."});
}
});
module.exports = router;
Isso conclui nossa API REST. Agora você pode criar aplicativos muito mais complexos usando esse estilo de arquitetura simples e o Express.
O andaime nos permite criar facilmente um skeleton for a web application. Nós criamos manualmente nosso diretório público, adicionamos middleware, criamos arquivos de rota separados, etc. Uma ferramenta de scaffolding configura tudo isso para nós para que possamos iniciar diretamente a construção de nosso aplicativo.
O andaime que usaremos é chamado Yeoman. É uma ferramenta de andaime construída paraNode.jsmas também tem geradores para vários outros frameworks (como flask, rails, django, etc.). Para instalar o Yeoman, digite o seguinte comando em seu terminal -
npm install -g yeoman
Yeoman usa geradores para criar aplicativos. Para verificar os geradores disponíveis emnpmpara usar com Yeoman, você pode clicar neste link . Neste tutorial, usaremos o 'generator-Express-simple' . Para instalar este gerador, digite o seguinte comando em seu terminal -
npm install -g generator-express-simple
Para usar este gerador, digite o seguinte comando -
yo express-simple test-app
Serão feitas algumas perguntas simples, como o que você deseja usar com seu aplicativo. Selecione as seguintes respostas ou, se você já conhece essas tecnologias, escolha como deseja que sejam.
express-simple comes with bootstrap and jquery
[?] Select the express version you want: 4.x
[?] Do you want an mvc express app: Yes
[?] Select the css preprocessor you would like to use: sass
[?] Select view engine you would like to use: jade
[?] Select the build tool you want to use for this project: gulp
[?] Select the build tool you want to use for this project: gulp
[?] Select the language you want to use for the build tool: javascript
create public/sass/styles.scss
create public/js/main.js
create views/layout.jade
create views/index.jade
create views/404.jade
create app.js
create config.js
create routes/index.js
create package.json
create bower.json
identical .bowerrc
identical .editorconfig
identical .gitignore
identical .jshintrc
create gulpfile.js
I'm all done. Running bower install & npm install for you to install the
required dependencies. If this fails, try running the command yourself.
Em seguida, ele criará um novo aplicativo para você, instalará todas as dependências, adicionará algumas páginas ao seu aplicativo (página inicial, página 404 não encontrada, etc.) e fornecerá uma estrutura de diretório para trabalhar.
Este gerador cria uma estrutura muito simples para nós. Explore os muitos geradores disponíveis para o Express e escolha aquele que mais se adapta a você. As etapas para trabalhar com todos os geradores são as mesmas. Você precisará instalar um gerador, execute-o usando Yeoman; ele fará algumas perguntas e, em seguida, criará um esqueleto para seu aplicativo com base em suas respostas.
O tratamento de erros no Express é feito usando middleware. Mas esse middleware tem propriedades especiais. O middleware de tratamento de erros é definido da mesma maneira que outras funções de middleware, exceto que as funções de tratamento de errosMUST have four arguments em vez de três - err, req, res, next. Por exemplo, para enviar uma resposta sobre qualquer erro, podemos usar -
app.use(function(err, req, res, next) {
console.error(err.stack);
res.status(500).send('Something broke!');
});
Até agora estávamos lidando com erros nas próprias rotas. O middleware de tratamento de erros nos permite separar nossa lógica de erro e enviar respostas de acordo. O método next () que discutimos no middleware nos leva ao próximomiddleware/route handler.
Para tratamento de erros, temos o next(err)função. Uma chamada para esta função ignora todo o middleware e nos corresponde ao próximo manipulador de erros para essa rota. Vamos entender isso por meio de um exemplo.
var express = require('express');
var app = express();
app.get('/', function(req, res){
//Create an error and pass it to the next function
var err = new Error("Something went wrong");
next(err);
});
/*
* other route handlers and middleware here
* ....
*/
//An error handling middleware
app.use(function(err, req, res, next) {
res.status(500);
res.send("Oops, something went wrong.")
});
app.listen(3000);
Este middleware de tratamento de erros pode ser colocado estrategicamente após as rotas ou conter condições para detectar tipos de erros e responder aos clientes de acordo. O programa acima exibirá a seguinte saída.
O Express usa o módulo Debug para registrar internamente informações sobre correspondência de rota, funções de middleware, modo de aplicativo, etc.
Para ver todos os logs internos usados no Express, defina a variável de ambiente DEBUG para Express:* ao iniciar o aplicativo -
DEBUG = express:* node index.js
A seguinte saída será exibida.
Esses registros são muito úteis quando um componente do seu aplicativo não está funcionando corretamente. Essa saída detalhada pode ser um pouco opressora. Você também pode restringir a variável DEBUG a uma área específica a ser registrada. Por exemplo, se você deseja restringir o logger ao aplicativo e ao roteador, pode usar o código a seguir.
DEBUG = express:application,express:router node index.js
A depuração está desativada por padrão e é ativada automaticamente no ambiente de produção. A depuração também pode ser estendida para atender às suas necessidades. Você pode ler mais sobre isso na página npm.
Diferente do Django e Rails que têm uma maneira definida de fazer as coisas, estrutura de arquivos, etc., o Express não segue uma maneira definida. Isso significa que você pode estruturar o aplicativo da maneira que desejar. Mas à medida que seu aplicativo cresce em tamanho, é muito difícil mantê-lo se ele não tiver uma estrutura bem definida. Neste capítulo, veremos as estruturas de diretório geralmente usadas e a separação de interesses para construir nossos aplicativos.
Primeiro, discutiremos as melhores práticas para a criação de aplicativos de nó e Express.
Sempre comece um projeto de nó usando npm init.
Sempre instale dependências com um --save ou --save-dev. Isso garantirá que, se você mudar para uma plataforma diferente, você pode apenas executar npm install para instalar todas as dependências.
Fique com nomes de arquivo em minúsculas e variáveis camelCase. Se você olhar para qualquer módulo npm, ele é nomeado em letras minúsculas e separado por travessões. Sempre que você precisar desses módulos, use camelCase.
Não envie node_modules para seus repositórios. Em vez disso, o npm instala tudo nas máquinas de desenvolvimento.
Use um config arquivo para armazenar variáveis
Agrupe e isole as rotas em seus próprios arquivos. Por exemplo, pegue as operações CRUD no exemplo de filmes que vimos na página da API REST.
Estrutura de Diretório
Vamos agora discutir a estrutura de diretórios do Express.
Sites
O Express não possui uma estrutura definida pela comunidade para a criação de aplicativos. A seguir está uma estrutura de projeto amplamente utilizada para um site.
test-project/
node_modules/
config/
db.js //Database connection and configuration
credentials.js //Passwords/API keys for external services used by your app
config.js //Other environment variables
models/ //For mongoose schemas
users.js
things.js
routes/ //All routes for different entities in different files
users.js
things.js
views/
index.pug
404.pug
...
public/ //All static content being served
images/
css/
javascript/
app.js
routes.js //Require all routes in this and then require this file in
app.js
package.json
Existem outras abordagens para construir sites com o Express também. Você pode construir um site usando o padrão de design MVC. Para obter mais informações, você pode visitar os links a seguir.
https://code.tutsplus.com/tutorials/build-a-complete-mvc-website-with-expressjs--net-34168
e,
https://www.terlici.com/2014/08/25/best-practices-express-structure.html.
APIs RESTful
APIs são mais simples de projetar; eles não precisam de um diretório público ou de visualizações. Use a seguinte estrutura para construir APIs -
test-project/
node_modules/
config/
db.js //Database connection and configuration
credentials.js //Passwords/API keys for external services used by your app
models/ //For mongoose schemas
users.js
things.js
routes/ //All routes for different entities in different files
users.js
things.js
app.js
routes.js //Require all routes in this and then require this file in
app.js
package.json
Você também pode usar um gerador de yeoman para obter uma estrutura semelhante.
Este capítulo lista os vários recursos que usamos para este tutorial.
O link mais importante é, obviamente, os documentos da API Express - https://expressjs.com/en/4x/api.html
Os guias fornecidos no site Express sobre diferentes aspectos também são bastante úteis -
Routing
Middleware
Manipulação de erros
Debugging
Uma lista de livros e blogs úteis no Express está disponível em https://expressjs.com/en/resources/books-blogs.html
Uma lista de middleware mais usado com Express está disponível em https://expressjs.com/en/resources/middleware.html
Esses blogs com dicas e truques do Express podem ser úteis -
https://derickbailey.com/categories/tips-and-tricks/
https://scotch.io/tutorials/learn-to-use-the-new-router-in+-expressjs-4
Estrutura do aplicativo - https://www.terlici.com/2014/08/25/best-practices-express-structure.html
APIs RESTful -
https://www.thepolyglotdeveloper.com/2015/10/create-a-simple-restful-api-with-node-js/
https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4
https://devcenter.heroku.com/articles/mean-apps-restful-api
https://pixelhandler.com/posts/develop-a-restful-api-using-nodejs-with-express-and-mongoose
http://cwbuecheler.com/web/tutorials/2014/restful-web-app-node-express-mongodb/
Para autenticação avançada, use PassportJS - http://passportjs.org