banner cibersistemas

Categories: Tecnologia

Aprenda Node + MongoDB criando um projeto de encurtador de URL


Se você quer aprender sobre algo, que maneira melhor do que construir um projeto em torno do que você quer aprender?

Nesta postagem do blog, aprenderemos sobre MongoDB, Mongoose, Node e outras tecnologias criando um aplicativo simples de encurtamento de URL.

Os encurtadores de URL estão por toda parte, desde links que você compartilha no Twitter até serviços populares como bit.ly. Mas você já se perguntou como poderia criar um encurtador de URL rápido para si mesmo?

Então, passaremos pela prática de construir um encurtador de URL com MongoDB como nossa solução de back-end. Este projeto vai lhe dar confiança no seu conhecimento e solidificar cada conceito que você aprender. Vamos começar.

Introdução ao projeto

Estaremos usando isso gratuitamente URL shortener sala de aula de codedamn para praticar e avaliar nosso progresso à medida que prosseguimos.

Estaremos usando as seguintes tecnologias:

  • Mangusto como ORM
  • MongoDB como banco de dados de back-end
  • Node.js como back-end
  • Um arquivo JS incorporado simples como front-end

Concluiremos este projeto em 7 etapas, que o levarão do início ao fim. Vamos começar os laboratórios agora.

Parte 1: Configurando o servidor Express

Primeiro, vamos configurar nosso servidor Node. Usaremos Express como estrutura para esta parte, pois é fácil de trabalhar. Aqui está o link para esta parte.

Podemos ver que este é um exercício razoavelmente fácil. Os únicos dois desafios que temos que superar são os seguintes:

A solução pode ser assim:

// Initialize express server on PORT 1337
const express = require('express')
const app = express()

app.get('/', (req, res) => {
 res.send('Hello World! - from codedamn')
})

app.get('/short', (req, res) => {
 res.send('Hello from short')
})

app.listen(process.env.PUBLIC_PORT, () => {
 console.log('Server started')
})

Simples e fácil. Criamos outra rota GET usando app.get, e deve fazer o trabalho.

Parte 2: Configurando nosso mecanismo de visualização

Agora que estamos familiarizados com a instalação Express, vamos dar uma olhada no .ejs modelo que temos. Aqui está o link para esta parte.

O mecanismo EJS permite que você transmita variáveis ​​com o código Node.js para o seu HTML e repita ou exiba-as antes de enviar uma resposta real ao servidor.

Dê uma olhada rápida no views/index.ejs Arquivo. Será semelhante à aparência de um arquivo HTML normal, exceto que você pode usar variáveis.

Aqui está o nosso atual index.js Arquivo:

Agora, você pode ver isso no index.js arquivo temos a linha app.set('view engine', 'ejs') . Diz ao Express para usar ejs como seu mecanismo de modelagem padrão.

Finalmente, veja que estamos usando res.render e passando apenas o nome do arquivo, não o caminho completo. Isso ocorre porque o Express irá procurar automaticamente dentro da pasta de visualizações para ver se há .ejs modelos.

Passamos variáveis ​​como o segundo argumento, que podemos acessar no arquivo EJS. Usaremos esse arquivo mais tarde, mas por enquanto vamos passar por um desafio rápido.

Para completar este desafio, só precisamos mudar o nome de Mehul para qualquer outra coisa.

Para passar neste desafio, veja o index.ejs primeiro arquivo e depois atualize seu nome para qualquer outra coisa que você desejar. Esta é uma boa solução:

const express = require('express')
const app = express()

app.set('view engine', 'ejs')

app.get('/', (req, res) => {
 res.render('index', { myVariable: 'My name is John!' })
})

app.listen(process.env.PUBLIC_PORT, () => {
 console.log('Server started')
})

Parte 3: Configurando o MongoDB

Agora que temos um pouco de compreensão de front-end e back-end, vamos prosseguir e configurar o MongoDB. Aqui está o link para esta parte.

Usaremos o Mongoose para conectar ao MongoDB. Mongoose é um ORM para MongoDB.

Simplesmente falando, o MongoDB é muito solto banco de dados, e permite todos os tipos de operações em qualquer coisa.

Embora seja bom para dados não estruturados, na maioria das vezes estamos realmente cientes de quais serão os dados (como registros de usuário ou registros de pagamento). Assim, podemos definir um esquema para MongoDB usando Mongoose. Isso facilita muitas funções para nós.

Por exemplo, uma vez que temos um esquema, podemos ter certeza de que a validação de dados e todas as verificações necessárias serão tratadas pelo Mongoose automaticamente. O Mongoose também nos dá várias funções auxiliares para tornar nossas vidas mais fáceis. Agora vamos configurá-lo.

Para completar esta parte, temos que cuidar dos seguintes pontos:

  • O pacote Mongoose NPM já foi instalado para você. Você pode diretamente require isto.
  • Conecte-se ao mongodb://localhost:27017/codedamn URL usando o mongoose.connect método.

Aqui está nosso arquivo index.js atual:

const express = require('express')
const app = express()
const mongoose = require('mongoose')

app.set('view engine', 'ejs')

app.get('/', (req, res) => {
 res.render('index')
})

app.post('/short', (req, res) => {
 const db = mongoose.connection.db
 // insert the record in 'test' collection

 res.json({ ok: 1 })
})

// Setup your mongodb connection here
// mongoose.connect(...)

// Wait for mongodb connection before server starts
app.listen(process.env.PUBLIC_PORT, () => {
 console.log('Server started')
})

Vamos preencher os marcadores de posição apropriados com o código relevante:

const express = require('express')
const app = express()
const mongoose = require('mongoose')

app.set('view engine', 'ejs')

app.get('/', (req, res) => {
 res.render('index')
})

app.post('/short', (req, res) => {
 const db = mongoose.connection.db
 // insert the record in 'test' collection
 db.collection('test').insertOne({ testCompleted: 1 })

 res.json({ ok: 1 })
})

// Setup your mongodb connection here
mongoose.connect('mongodb://localhost/codedamn', {
 useNewUrlParser: true,
 useUnifiedTopology: true
})
mongoose.connection.on('open', () => {
 // Wait for mongodb connection before server starts
 app.listen(process.env.PUBLIC_PORT, () => {
  console.log('Server started')
 })
})

Observe como iniciamos nosso servidor HTTP apenas quando nossa conexão com o MongoDB está aberta. Isso é bom porque não queremos que os usuários atinjam nossas rotas antes que nosso banco de dados esteja pronto.

Finalmente usamos o db.collection método aqui para inserir um registro simples, mas teremos uma maneira melhor em breve de interagir com o banco de dados usando modelos Mongoose.

Parte 4: Configurando um esquema Mongoose

Agora que tivemos nossa experiência prática com a implementação do MongoDB na última seção, vamos desenhar o esquema para nosso encurtador de URL. Aqui está o link para esta parte.

Um esquema Mongoose nos permite interagir com as coleções Mongo de uma maneira abstrata. Os documentos ricos do Mongoose também expõem funções auxiliares como .save que são suficientes para realizar uma consulta de banco de dados completa para atualizar as alterações em seu documento.

Veja como ficará nosso esquema para o encurtador de URL:

const mongoose = require('mongoose')
const shortId = require('shortid')

const shortUrlSchema = new mongoose.Schema({
  full: {
    type: String,
    required: true
  },
  short: {
    type: String,
    required: true,
    default: shortId.generate
  },
  clicks: {
    type: Number,
    required: true,
    default: 0
  }
})

module.exports = mongoose.model('ShortUrl', shortUrlSchema)

Iremos armazenar este arquivo no models/url.js Arquivo. Assim que tivermos o esquema, podemos passar por esta parte do exercício. Temos que fazer as seguintes duas coisas:

  1. Crie este modelo no models/url.js Arquivo. (Nós fizemos isso.)
  2. Uma solicitação POST para /short deve adicionar algo ao banco de dados para este modelo.

Para fazer isso, podemos gerar um novo registro usando o seguinte código:

app.post('/short', async (req, res) => {
 // insert the record using the model
 const record = new ShortURL({
  full: 'test'
 })
 await record.save()
 res.json({ ok: 1 })
})

Você verá que podemos omitir o clicks e short campo porque eles já têm um valor padrão no esquema. Isso significa que o Mongoose os preencherá automaticamente quando a consulta for executada.

Nosso final index.js arquivo para passar neste desafio deve ser assim:

const express = require('express')
const app = express()
const mongoose = require('mongoose')
// import the model here
const ShortURL = require('./models/url')

app.set('view engine', 'ejs')

app.get('/', (req, res) => {
 res.render('index', { myVariable: 'My name is John!' })
})

app.post('/short', async (req, res) => {
 // insert the record using the model
 const record = new ShortURL({
  full: 'test'
 })
 await record.save()
 res.json({ ok: 1 })
})

// Setup your mongodb connection here
mongoose.connect('mongodb://localhost/codedamn')

mongoose.connection.on('open', () => {
 // Wait for mongodb connection before server starts
 app.listen(process.env.PUBLIC_PORT, () => {
  console.log('Server started')
 })
})

Parte 5: vinculando front-end, back-end, + MongoDB

Agora que temos uma alça na parte de backend, vamos voltar ao frontend e configurar nossa página da web. Lá podemos usar o Encolher botão para realmente adicionar alguns registros ao banco de dados. Aqui está o link para esta parte.

Se você olhar dentro do views/index.ejs arquivo, você verá que já passamos os dados do formulário no backend /short rota. Mas agora não estamos agarrando isso.

  • Você pode ver que há uma nova linha chamada app.use(express.urlencoded({ extended: false })) na linha 8, que nos permite ler a resposta do usuário no formulário.
  • No index.ejs arquivo, você pode ver que definimos name=”fullURL” que é como podemos receber o URL no back-end.

Aqui está o nosso index.ejs Arquivo:

<!DOCTYPE html>
<html lang="en">
 <head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <link
   rel="stylesheet"
   href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
  />
  <title>codedamn URL Shortner Project</title>
 </head>
 <body>
  <div class="container">
   <h1>URL Shrinker</h1>
   <form action="/short" method="POST" class="my-4 form-inline">
    <label for="fullUrl" class="sr-only">URL</label>
    <input
     required
     placeholder="URL"
     type="url"
     name="fullUrl"
     id="fullUrl"
     class="form-control col mr-2"
    />
    <button class="btn btn-success" type="submit">Shrink This!</button>
   </form>

   <table class="table table-striped table-responsive">
    <thead>
     <tr>
      <th>Full URL</th>
      <th>Short URL</th>
      <th>Clicks</th>
     </tr>
    </thead>
    <tbody>
     <% shortUrls.forEach(shortUrl => { %>
     <tr>
      <td><a href="<%= shortUrl.full %>"><%= shortUrl.full %></a></td>
      <td><a href="<%= shortUrl.short %>"><%= shortUrl.short %></a></td>
      <td><%= shortUrl.clicks %></td>
     </tr>
     <% }) %>
    </tbody>
   </table>
  </div>
 </body>
</html>

Este é um desafio simples, porque só precisamos inserir este código para completá-lo:

app.use(express.urlencoded({ extended: false }))

app.post('/short', async (req, res) => {
 // Grab the fullUrl parameter from the req.body
 const fullUrl = req.body.fullUrl
 console.log('URL requested: ', fullUrl)

 // insert and wait for the record to be inserted using the model
 const record = new ShortURL({
  full: fullUrl
 })

 await record.save()

 res.redirect('/')
})

Primeiro de tudo, pegamos o URL enviado por HTML usando o req.body.fullUrl. Para habilitar isso, também temos app.use(express.urlencoded({ extended: false })) o que nos permite obter os dados do formulário.

Em seguida, criamos e salvamos nosso registro exatamente como fizemos da última vez. Por fim, redirecionamos o usuário de volta à página inicial para que ele possa ver os novos links.

Dica: Você pode tornar este aplicativo mais interessante executando uma solicitação Ajax para a API de back-end em vez do envio de formulário típico. Mas vamos deixá-lo aqui, pois ele se concentra mais na configuração do MongoDB + Node em vez do JavaScript.

Parte 6: Exibindo URLs curtos no front-end

Agora que estamos armazenando URLs encurtados no MongoDB, vamos prosseguir e mostrá-los no front-end também.

Lembre-se de nossas variáveis ​​passadas para o ejs modelo de antes? Agora vamos usá-los.

O loop de modelo para ejs foi feito para você no index.ejs arquivo (você pode ver aquele loop acima). No entanto, temos que escrever a consulta Mongoose para extrair os dados nesta seção.

Se virmos o modelo, veremos isso em index.js temos o seguinte código:

app.get('/', (req, res) => {
 const allData = [] // write a mongoose query to get all URLs from here
 res.render('index', { shortUrls: allData })
})

Já temos um modelo definido conosco para consultar dados do Mongoose. Vamos usá-lo para obter tudo o que precisamos.

Aqui está nosso arquivo de solução:

const express = require('express')
const app = express()
const mongoose = require('mongoose')
// import the model here
const ShortURL = require('./models/url')

app.set('view engine', 'ejs')
app.use(express.urlencoded({ extended: false }))

app.get('/', async (req, res) => {
 const allData = await ShortURL.find()
 res.render('index', { shortUrls: allData })
})

app.post('/short', async (req, res) => {
 // Grab the fullUrl parameter from the req.body
 const fullUrl = req.body.fullUrl
 console.log('URL requested: ', fullUrl)

 // insert and wait for the record to be inserted using the model
 const record = new ShortURL({
  full: fullUrl
 })

 await record.save()

 res.redirect('/')
})

// Setup your mongodb connection here
mongoose.connect('mongodb://localhost/codedamn', {
 useNewUrlParser: true,
 useUnifiedTopology: true
})

mongoose.connection.on('open', async () => {
 // Wait for mongodb connection before server starts

 // Just 2 URLs for testing purpose
 await ShortURL.create({ full: 'http://google.com' })
 await ShortURL.create({ full: 'http://codedamn.com' })

 app.listen(process.env.PUBLIC_PORT, () => {
  console.log('Server started')
 })
})

Você pode ver que foi tão fácil quanto fazer await ShortURL.find() no allData variável. A próxima parte é onde as coisas ficam um pouco complicadas.

Parte 7: Fazendo o redirecionamento funcionar

Estamos quase terminando! Temos o URL completo e o URL curto armazenados no banco de dados agora, e os mostramos no frontend também.

Mas você notará que o redirecionamento não funciona agora e obtemos um erro do Express.

Vamos consertar isso. Você pode ver no index.js arquivo, há uma nova rota dinâmica adicionada no final que lida com esses redirecionamentos:

app.get('/:shortid', async (req, res) => {
 // grab the :shortid param
 const shortid = ''

 // perform the mongoose call to find the long URL

 // if null, set status to 404 (res.sendStatus(404))

 // if not null, increment the click count in database

 // redirect the user to original link
})

Nossos desafios para esta parte são assim:

Tudo bem. Em primeiro lugar, temos que extrair o URL completo quando visitamos um URL curto. Veja como faremos isso:

app.get('/:shortid', async (req, res) => {
 // grab the :shortid param
 const shortid = req.params.shortid

 // perform the mongoose call to find the long URL
 const rec = await ShortURL.findOne({ short: shortid })

 // ...
})

Agora, se virmos que nosso resultado é nulo, enviaremos um status 404:

app.get('/:shortid', async (req, res) => {
 // grab the :shortid param
 const shortid = req.params.shortid

 // perform the mongoose call to find the long URL
 const rec = await ShortURL.findOne({ short: shortid })

 // if null, set status to 404 (res.sendStatus(404))
 if (!rec) return res.sendStatus(404)

 res.sendStatus(200) 
})

Isso supera nosso primeiro desafio. A seguir, se de fato temos um link, vamos redirecionar o usuário e incrementar a contagem de cliques também no banco de dados.

app.get('/:shortid', async (req, res) => {
 // grab the :shortid param
 const shortid = req.params.shortid

 // perform the mongoose call to find the long URL
 const rec = await ShortURL.findOne({ short: shortid })

 // if null, set status to 404 (res.sendStatus(404))
 if (!rec) return res.sendStatus(404)

 // if not null, increment the click count in database
 rec.clicks++
 await rec.save()

 // redirect the user to original link
 res.redirect(rec.full)
})

Dessa forma, podemos incrementar e armazenar o resultado no banco de dados novamente. E isso deve superar todos os nossos desafios.

Conclusão

Parabéns! Você acabou de construir um encurtador de URL totalmente funcional usando Express + Node + MongoDB. Dê um tapinha nas costas!

O código-fonte final é disponível no GitHub.

Se você tiver algum feedback sobre este artigo ou sobre as salas de aula codificadas, sinta-se à vontade para entrar em contato comigo no Twitter. Vamos discutir 🙂



Fonte

Click to rate this post!
[Total: 0 Average: 0]
Share
Published by
António César de Andrade

Recent Posts

Kojima Productions começou seu próximo jogo e está contratando

Um pouco menos de um ano desde o lançamento do ambicioso Death Stranding, a Kojima…

21 mins ago

Yakuza: Like A Dragon tem tempos de carregamento “quase instantâneos” no Xbox Series X

Yakuza: Like a Dragon está entre os mais de 30 títulos de lançamento do Xbox…

7 hours ago

A atualização final do Super Smash Bros. faz uma mudança muito importante para Steve do Minecraft

A nova atualização 9.0.1 para Super Smash Bros. Ultimate foi oficialmente publicada e contém uma…

9 hours ago

O streaming de AOC entre nós funciona porque é genuíno

A congressista de Nova York Alexandria Ocasio-Cortez fez sua estréia no Twitch transmitindo entre nós…

10 hours ago

Call Of Duty: Revelada a música tema principal da Black Ops Cold War; Jack Wall Returns

Call of Duty: Black Ops Cold War trouxe de volta o compositor do Black Ops…

12 hours ago

Doom Eternal: Ancient Gods DLC First Mission Gameplay

DOOM Eternal Lançado pela primeira vez 19 de março de 2020liberado Nintendo Switch PC +…

12 hours ago

This website uses cookies.