Crie um Encurtador de URLs com Flask e MySQL

HTMLBeginner
Pratique Agora

Introdução

Este projeto guia você através da criação de um serviço simples de encurtamento de URLs usando Flask e MySQL. Você aprenderá a configurar um banco de dados, projetar uma interface web e implementar funcionalidades para encurtar URLs, pesquisar URLs por tags e visualizar análises. O projeto é amigável para iniciantes e oferece uma visão abrangente do desenvolvimento web com Python e gerenciamento de banco de dados.

O projeto é baseado em https://github.com/highoncarbs/shorty, que é originalmente licenciado sob a licença MIT.

👀 Pré-visualização

Converter a URL com/sem sufixo personalizado, pesquisar URLs por tag, acessar o link:

Visualizar informações sobre o sistema operacional e a plataforma usados para acessar o link:

🎯 Tarefas

Neste projeto, você aprenderá:

  • Como conectar uma aplicação Flask a um banco de dados MySQL
  • Como criar e gerenciar um esquema de banco de dados MySQL para armazenar informações de URL
  • Como implementar páginas web frontend usando HTML e CSS para interagir com o backend
  • Como lidar com dados de formulário e requisições no Flask para criar URLs curtas
  • Como desenvolver funcionalidades para redirecionar usuários de uma URL curta para a URL original
  • Como criar uma funcionalidade simples de análise para rastrear o uso de URLs, incluindo contagens de cliques e informações básicas sobre navegador/plataforma
  • Como projetar tratamento de erros amigável ao usuário e páginas 404 personalizadas para uma melhor experiência do usuário

🏆 Conquistas

Após concluir este projeto, você será capaz de:

  • Realizar operações básicas com MySQL, incluindo criação de banco de dados e tabelas, inserção de dados e consultas
  • Entender os fundamentos do Flask, incluindo roteamento, tratamento de requisições e renderização de templates
  • Trabalhar com formulários HTML e processar dados em uma aplicação Flask
  • Aplicar princípios básicos de design frontend e usar CSS para criar uma interface web visualmente atraente
  • Implementar análises simples para coletar e exibir dados sobre o uso de URLs
  • Implementar as melhores práticas para tratamento de erros em aplicações web para melhorar a confiabilidade e a experiência do usuário

Configurar o Ambiente do Projeto

Primeiramente, precisamos configurar o ambiente do nosso projeto no terminal. Isso envolve a instalação do pacote Python necessário para a conectividade com o MySQL e o início do serviço MySQL. Uma vez que o serviço estiver ativo, criaremos um banco de dados e uma tabela para armazenar nossas URLs.

Instalar PyMySQL:

pip install PyMySQL==1.1.0

Iniciar o serviço MySQL e fazer login no shell do MySQL:

sudo service mysql start
mysql -u root

Dentro do shell do MySQL, execute os seguintes comandos para criar o banco de dados e a tabela:

Criar banco de dados:

CREATE DATABASE IF NOT EXISTS SHORTY;
USE SHORTY;

Criar tabela:

CREATE TABLE IF NOT EXISTS WEB_URL
(
    ID             INT AUTO_INCREMENT,
    URL            VARCHAR(512),
    S_URL          VARCHAR(80),
    TAG            VARCHAR(80),
    COUNTER        INT DEFAULT 0,
    CHROME         INT DEFAULT 0,
    FIREFOX        INT DEFAULT 0,
    SAFARI         INT DEFAULT 0,
    OTHER_BROWSER  INT DEFAULT 0,
    ANDROID        INT DEFAULT 0,
    IOS            INT DEFAULT 0,
    WINDOWS        INT DEFAULT 0,
    LINUX          INT DEFAULT 0,
    MAC            INT DEFAULT 0,
    OTHER_PLATFORM INT DEFAULT 0,
    PRIMARY KEY (ID)
);

Esta instrução SQL cria uma tabela chamada WEB_URL no banco de dados SHORTY, projetada para armazenar informações relacionadas a URLs encurtadas e algumas análises associadas.

  • CREATE TABLE IF NOT EXISTS WEB_URL: Este comando cria uma nova tabela chamada WEB_URL somente se ela ainda não existir no banco de dados. Isso ajuda a evitar erros quando o script é executado várias vezes.
  • ID INT AUTO_INCREMENT: Esta coluna é designada como a chave primária para a tabela e é definida para incrementar automaticamente com cada nova entrada. Isso significa que toda vez que um novo registro é adicionado, o MySQL atribuirá automaticamente um ID exclusivo, incrementando em 1 a partir do último.
  • URL VARCHAR(512): Esta coluna armazena as URLs originais que estão sendo encurtadas. O tipo de dado VARCHAR(512) significa que pode conter strings de comprimento variável, até 512 caracteres.
  • S_URL VARCHAR(80): Esta é a coluna para a string da URL encurtada, com um comprimento máximo de 80 caracteres.
  • TAG VARCHAR(80): Esta coluna destina-se a armazenar tags associadas às URLs para fins de categorização ou pesquisa, com um comprimento máximo de 80 caracteres.
  • COUNTER INT DEFAULT 0: Esta coluna inteira é provavelmente usada para rastrear o número de vezes que uma URL encurtada foi acessada. Ele é definido como 0 por padrão na criação de um novo registro.
    As próximas colunas são projetadas para conter dados de análise para as URLs encurtadas:
  • CHROME, FIREFOX, SAFARI, OTHER_BROWSER: Estas colunas são usadas para rastrear o número de visitas de diferentes navegadores web. Cada uma é uma coluna inteira que é definida como 0 por padrão.
  • ANDROID, IOS, WINDOWS, LINUX, MAC, OTHER_PLATFORM: Semelhante às colunas do navegador, estas destinam-se a rastrear visitas de diferentes sistemas operacionais/plataformas, com cada coluna sendo definida como 0 por padrão.
  • PRIMARY KEY (ID): Esta parte da instrução especifica que a coluna ID é a chave primária da tabela. Uma chave primária é um identificador exclusivo para cada registro na tabela, garantindo que dois registros não tenham o mesmo ID.

Esta estrutura de tabela permite armazenar, recuperar e analisar dados sobre URLs encurtadas, incluindo com que frequência elas são acessadas, de quais navegadores e de quais sistemas operacionais.

Para sair do shell do MySQL, você pode executar o seguinte comando:

EXIT;
✨ Verificar Solução e Praticar

Criar o Template da Página Inicial

A página inicial é onde os usuários interagirão com o encurtador de URLs. Usaremos HTML e a linguagem de template do Flask para criar conteúdo dinâmico.

Em templates/index.html, adicione o seguinte código HTML:

<!doctype html>
<html>
  <head>
    <title>Shorty</title>
    <!-- Add Local SVG image when hosting. -->
    <link
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet"
    />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.7.1/clipboard.min.js"></script>
    <link rel="stylesheet" type="text/css" href="../static/skeleton.css" />
    <link rel="stylesheet" type="text/css" href="../static/normalize.css" />
    <link rel="stylesheet" type="text/css" href="../static/main.css" />
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,700,900"
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="container  main_header">
      <h3 align="left"><a href="{{url_for('index')}}">Shorty</a></h3>
      <p>A very simple URL shortening service.</p>
    </div>

    <div class="u-full-width shorty">
      <div class="container"></div>
    </div>
  </body>
</html>

Aqui está uma visão geral de seus principais componentes:

  • Google Material Icons: A tag <link> importa a biblioteca Google Material Icons, permitindo o uso de ícones predefinidos para uma interface de usuário mais envolvente.
  • Clipboard.js: A tag <script> inclui a biblioteca Clipboard.js, uma biblioteca JavaScript popular para copiar conteúdo para a área de transferência. Isso pode ser útil para um encurtador de URLs, permitindo que os usuários copiem facilmente URLs encurtadas.
  • Folhas de estilo (Stylesheets): O template vincula-se a vários arquivos CSS para estilização:
    • skeleton.css: Um framework CSS leve que fornece estilo básico e um sistema de grade responsivo.
    • normalize.css: Redefine os estilos padrão do navegador para manter a estilização consistente em diferentes navegadores.
    • main.css: Contém estilos personalizados específicos para o serviço "Shorty".
  • Google Fonts: Outra tag <link> importa a família de fontes "Roboto" do Google Fonts, fornecendo uma variedade de pesos de fonte para design de tipografia.
  • Dentro do <body>, uma div com a classe container main_header é usada para criar uma seção de cabeçalho, que inclui:
    • Um título (<h3>) contendo um link (<a>) que redireciona para a página inicial, facilitado pela função url_for do Flask, gerando dinamicamente a URL para a rota 'index'.
    • Um parágrafo (<p>) descrevendo o serviço como "A very simple URL shortening service." (Um serviço de encurtamento de URL muito simples.)
✨ Verificar Solução e Praticar

Implementar Encurtamento de URL e Pesquisa por Tags

Nesta etapa, aprimoraremos a interface web integrando duas funcionalidades chave: encurtamento de URL e pesquisa de URL baseada em tags. Isso permitirá que os usuários não apenas encurtem URLs, mas também as organizem e recuperem de forma eficiente usando tags.

Encurtamento de URL

Primeiro, criaremos um formulário na página inicial onde os usuários podem inserir a URL que desejam encurtar. Campos opcionais para sufixos personalizados e tags permitirão URLs curtas personalizadas e categorização para facilitar o gerenciamento.

Adicione o seguinte código a templates/index.html:

<!-- Search URL block -->
<div class="search_url_block">
  <form method="post" action="/search" name="search_tag_block">
    <input type="text" name="search_url" placeholder="Search tags " />
    <button type="submit" class="button-primary search_url_btn" value="Search">
      Search
    </button>
  </form>
</div>
<!-- end block -->

O primeiro bloco de código adiciona um formulário projetado para pesquisar URLs por suas tags associadas:

  • search_url_block: Este contêiner contém o formulário de pesquisa, tornando-o uma seção distinta na página para melhor organização e estilização.
  • <form>: Define um formulário que envia uma requisição POST para o endpoint /search quando o botão de pesquisa é clicado. Este formulário é nomeado search_tag_block para identificação.
  • <input>: Um campo de entrada de texto onde os usuários podem inserir tags que desejam pesquisar. O atributo placeholder fornece uma dica ao usuário sobre o propósito do campo.
  • <button>: Um botão de envio que inicia o envio do formulário. A classe button-primary provavelmente adiciona uma estilização específica definida no CSS.

Pesquisa Baseada em Tags

Para complementar a funcionalidade de encurtamento de URL, também implementaremos uma funcionalidade que permite aos usuários pesquisar URLs por tags. Este recurso será integrado ao template index, fornecendo um formulário simples onde os usuários podem inserir tags para encontrar as URLs correspondentes.

Adicione o seguinte código a templates/index.html:

<!-- URL Input block -->
<form method="post" action="" name="generate_block">
  <div class="row">
    <input type="text" name="url_input" placeholder="Enter URL" />
    <input type="text" name="url_custom" placeholder="Enter Custom Suffix" />
    <input type="text" name="url_tag" placeholder="Tag URL" />
    <button class="button-primary generate">Generate</button>
  </div>
</form>
<!-- end block -->

O segundo bloco de código introduz um formulário para os usuários encurtarem URLs, com campos adicionais para personalização:

  • Todo o formulário está envolvido em um elemento <form> com method="post" e um atributo action não especificado. Isso significa que os dados do formulário serão enviados via requisição POST para a URL atual quando o botão gerar for clicado.
  • Dentro do formulário, um <div> com a classe row provavelmente ajuda no layout e alinhamento, garantindo que os campos de entrada e o botão sejam organizados adequadamente.
  • Três elementos <input type="text"> são fornecidos para diferentes propósitos:
    • O primeiro campo de entrada é para os usuários inserirem a URL original que desejam encurtar.
    • O segundo permite um sufixo personalizado opcional para a URL encurtada, permitindo que os usuários personalizem seus links curtos.
    • O terceiro campo é designado para tags, permitindo que os usuários categorizem ou adicionem rótulos descritivos às suas URLs encurtadas para facilitar a recuperação e o gerenciamento.
  • Um <button> com a classe button-primary e o texto "Generate" serve como o botão de envio do formulário. Clicar neste botão envia os dados para o servidor para criar uma URL encurtada com as informações fornecidas.

Essas melhorias melhoram significativamente a experiência do usuário, oferecendo mais funcionalidade além do encurtamento básico de URL. A capacidade de pesquisar URLs por tags permite o gerenciamento e a recuperação eficientes de links encurtados, enquanto a opção de adicionar sufixos personalizados e tags permite a personalização e categorização de URLs. Essa configuração utiliza formulários HTML para coletar a entrada do usuário, que será então processada pela aplicação Flask do lado do servidor para realizar as ações desejadas.

✨ Verificar Solução e Praticar

Lidar com Erros e Exibir URLs Encurtadas

Nesta etapa, focamos em aprimorar a experiência do usuário, lidando com mensagens de erro e exibindo as URLs encurtadas.

Lidar com Erros

Primeiramente, adicionamos funcionalidade para exibir mensagens de erro aos usuários. Isso é crucial para fornecer feedback quando algo dá errado, como quando um usuário envia uma URL inválida ou uma tag que não existe. O tratamento adequado de erros torna a aplicação mais robusta e amigável ao usuário.

Adicione o seguinte código a templates/index.html:

<!-- Error Display block -->
{% if error != '' %}
<p class="error_disp">{{error}}</p>
{% endif %} {% if shorty_url %}
<!-- end block-->

Este bloco foi projetado para fornecer feedback ao usuário se ocorrer um erro durante o processo de encurtamento de URL:

  • {% if error != '' %}: Esta é uma declaração condicional usando a sintaxe de template do Flask, Jinja2. Ela verifica se a variável error não está vazia. Espera-se que a variável error seja passada do backend Flask para o template. Se houver uma mensagem de erro, a condição é avaliada como True.
  • <p class="error_disp">{{error}}</p>: Quando a condição é True, este elemento de parágrafo é renderizado, exibindo a mensagem de erro contida na variável error. A classe error_disp provavelmente é usada para estilizar a mensagem de erro, tornando-a visualmente distinta para chamar a atenção do usuário.
  • {% endif %}: Isso fecha o bloco condicional. Se a variável error estiver vazia, nada deste bloco será renderizado na página.

Exibir URLs Encurtadas

Em segundo lugar, após uma URL ser encurtada com sucesso, exibimos a URL encurtada ao usuário. Isso envolve a criação de uma seção na página inicial que mostra dinamicamente a URL encurtada após o envio do formulário, completa com um botão de copiar para a área de transferência para facilitar o compartilhamento.

Adicione o seguinte código a templates/index.html:

<!-- URL Generator Display block -->
<div class="gen_block">
  <p class="gen_url">
    Shorty URL is
    <b><a id="short-url" href="{{shorty_url}}">{{shorty_url}}</a></b>
  </p>
  <button
    class="button-primary copy-btn"
    data-clipboard-action="copy"
    data-clipboard-target="#short-url"
  >
    Copy
  </button>
</div>
{% endif %}
<!-- end block -->

Este bloco é exibido quando uma URL foi encurtada com sucesso e fornece uma maneira para os usuários copiarem a URL encurtada facilmente:

  • {% if shorty_url %}: Outra declaração condicional que verifica se a variável shorty_url existe e não está vazia. Esta variável deve conter a URL encurtada gerada pelo serviço.
  • <p class="gen_url">: Este parágrafo exibe uma mensagem indicando a URL encurtada. Dentro dele, <a id="short-url" href="{{shorty_url}}">{{shorty_url}}</a> cria um hiperlink com a URL encurtada como texto do link e o atributo href, permitindo que os usuários cliquem nele diretamente.
  • <button>: Este botão foi projetado para copiar a URL encurtada para a área de transferência para facilitar o compartilhamento. Ele usa classes para estilização (button-primary) e funcionalidade (copy-btn). O atributo data-clipboard-action especifica a ação a ser executada (copiar) e data-clipboard-target indica o elemento de destino para copiar (o link da URL encurtada). Esta configuração assume a integração do Clipboard.js (ou uma biblioteca similar) para lidar com a funcionalidade de cópia.
  • {% endif %}: Fecha o bloco condicional para exibir a URL encurtada e o botão de copiar. Se shorty_url não estiver definido ou estiver vazio, esta seção não será renderizada.

Essas melhorias contribuem significativamente para a usabilidade do serviço de encurtamento de URL. A mensagem de erro fornece feedback essencial, guiando os usuários a corrigir erros ou informando-os sobre problemas, enquanto a exibição de URLs encurtadas com uma função de cópia fácil permite uma experiência perfeita na criação e compartilhamento de links encurtados.

✨ Verificar Solução e Praticar

Listar e Gerenciar URLs Encurtadas

A etapa final é criar uma seção que liste todas as URLs encurtadas armazenadas no banco de dados, juntamente com suas URLs originais, o número de cliques que receberam e links para análises detalhadas. Essa funcionalidade permite que os usuários visualizem e gerenciem suas URLs encurtadas em um só lugar, tornando a aplicação mais funcional e amigável.

Adicione o seguinte código a templates/index.html:

        <!-- URL List Block -->
        {% if not error %}
        {% if not shorty_url %}
        <!-- Add Empty list case -> 'Wow . Such Empty!' -->
        <div style="overflow-x:auto;">
            <div class="table_list u-full-width">
                <table>
                    <thead>
                    <tr>
                        <th>Original URL</th>
                        <th>Short URL</th>
                        <th>Clicks</th>
                        <th>Info</th>
                    </tr>
                    </thead>

                    <tbody>
                    {% for url in table %}
                    <tr>
                        <td style="padding-left: 5px;">{{url[1]}}</td>
                        <td><a href="{{host+url[2]}}">{{ host+url[2]}}</a></td>
                        <td style="text-align: center;">{{url[4]}}</td>
                        <td id="info"><a href=" {{url_for('analytics' ,short_url=url[2])}} "><i class="material-icons">info_outline</i></a>
                        </td>
                    </tr>

                    {% endfor %}
                    </tbody>
                </table>
            </div>
        </div>
        {% endif %}
        {% endif %}
    </div>
</div>
<script type="text/javascript">
    var clipboard = new Clipboard('.copy-btn');
</script>
</html>

Este código foi projetado para listar todas as URLs encurtadas armazenadas no banco de dados, fornecendo informações como a URL original, a URL encurtada, o número de cliques e links para análises mais detalhadas. Aqui está uma análise detalhada de seus componentes:

  • O bloco começa com um condicional {% if not error %} para garantir que a lista seja exibida apenas quando não houver erro. Isso ajuda a manter uma interface de usuário limpa, especialmente quando mensagens de erro precisam ser exibidas.
  • Outro condicional {% if not shorty_url %} verifica se uma nova URL encurtada não foi gerada recentemente. Essa condição pode ser usada para impedir que a lista seja exibida imediatamente após uma nova URL ser encurtada, concentrando a atenção do usuário na URL encurtada recém-criada.
  • Um estilo overflow-x:auto; é aplicado a uma div para garantir que a tabela seja rolável horizontalmente em telas menores, aprimorando a capacidade de resposta e a usabilidade.
  • O elemento table é estruturado com uma seção thead definindo os cabeçalhos das colunas para "Original URL", "Short URL", "Clicks" e "Info". Este layout ajuda os usuários a entender os dados apresentados.
  • A seção tbody é preenchida dinamicamente com dados usando um loop Flask/Jinja2: {% for url in table %}. Este loop itera sobre uma coleção de URLs (table) passadas do backend Flask, exibindo os dados de cada URL em uma nova linha de tabela (<tr>).
  • Dentro de cada linha, a URL original é exibida em uma célula (<td>) com algum preenchimento para estética. A URL encurtada é apresentada como um link clicável (<a>), construído anexando o caminho encurtado (url[2]) ao nome do host (host), que também deve ser passado do backend.
  • A coluna "Clicks" mostra o número de vezes que a URL encurtada foi acessada, centralizada para melhor legibilidade.
  • A coluna "Info" contém um link para a página de análise de cada URL encurtada. Este link é gerado usando a função url_for do Flask, criando dinamicamente uma URL para a rota de análise com a URL encurtada como um parâmetro. Um ícone (<i class="material-icons">info_outline</i>) do conjunto de ícones do Google Material Icons é usado para representar o link de análise visualmente.
  • A tag {% endfor %} fecha o loop, garantindo que uma linha seja criada para cada URL na coleção table.
  • Os blocos condicionais são fechados com as tags {% endif %}.
  • Na parte inferior, uma tag <script> inicializa o Clipboard.js para a classe .copy-btn, que pode ter sido usada nas seções anteriores (por exemplo, para copiar a URL encurtada). Este script garante que qualquer elemento com a classe copy-btn terá a funcionalidade de copiar para a área de transferência habilitada, aproveitando a biblioteca Clipboard.js.

Esta etapa finaliza a funcionalidade do serviço de encurtamento de URL "Shorty", fornecendo aos usuários uma visão geral abrangente de suas URLs encurtadas, tornando mais fácil gerenciar e analisar seus links. A integração da renderização de dados dinâmicos com Flask/Jinja2, combinada com um design de interface do usuário atencioso, garante uma experiência amigável.

✨ Verificar Solução e Praticar

Criar o Template da Página de Pesquisa

Para permitir que os usuários pesquisem URLs por tags, precisaremos de uma página de pesquisa.

Em templates/search.html, adicione o seguinte código HTML:

<!DOCTYPE html>
<html>
<head>
    <title>Shorty</title>
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons"
          rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="../static/skeleton.css">
    <link rel="stylesheet" type="text/css" href="../static/normalize.css">
    <link rel="stylesheet" type="text/css" href="../static/main.css">
    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,700,900" rel="stylesheet">
</head>
<body>
<div class="container main_header">
    <h3 align="left"><a href="{{url_for('index')}}">Shorty</a></h3>
    <p>A dead simple URL shortener service.</p>
</div>
<!-- Search results  -->
<div class=" container search_header">
    <h4>Search Results for : <b> {{ search_tag }} <b></h4>

    <div style="overflow-x:auto;">
        <div class="table_list u-full-width">
            <table>
                <thead>
                <tr>
                    <th>Original URL</th>
                    <th>Short URL</th>
                    <th>Clicks</th>
                    <th>Info</th>

                </tr>
                </thead>

                <tbody>
                {% for url in table %}
                <tr>
                    <td style="padding-left: 5px;">{{url[1]}}</td>
                    <td><a href="{{ host+url[2]}}">{{host+url[2]}}</a></td>
                    <td style="text-align: center;">{{url[4]}}</td>
                    <td id="info"><a href=" {{url_for('analytics' ,short_url=url[2])}} "><i class="material-icons">info_outline</i></a>
                    </td>
                </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>

Este código cria um template para a página de resultados de pesquisa no serviço de encurtamento de URL "Shorty". Esta página foi projetada para exibir os resultados da pesquisa de um usuário por URLs por tags. Aqui está uma análise detalhada do template:

  • Dentro do <body>, a seção de cabeçalho (<div class="container main_header">) espelha a página de índice, fornecendo uma aparência consistente. Ele inclui o nome do serviço ("Shorty") como um link clicável que redireciona para a página de índice ({{url_for('index')}}) e uma breve descrição do serviço.
  • A seção <div class="container search_header"> introduz a área de resultados da pesquisa, começando com um cabeçalho (<h4>) que exibe dinamicamente a tag usada para a pesquisa ({{ search_tag }}).
  • Os resultados são apresentados em uma tabela dentro de uma div estilizada para rolagem horizontal (overflow-x:auto;), garantindo acessibilidade em dispositivos com telas menores.
  • A estrutura da tabela (<table>) consiste em seções de cabeçalho (<thead>) e corpo (<tbody>). O cabeçalho define colunas para "Original URL", "Short URL", "Clicks" e "Info", semelhante à lista exibida na página de índice.
  • O corpo da tabela é preenchido dinamicamente usando um loop ({% for url in table %}), iterando sobre uma coleção de URLs (table) passadas do backend Flask. Cada iteração cria uma nova linha (<tr>) na tabela para uma URL:
    • A URL original é exibida com algum preenchimento para melhor legibilidade.
    • A URL encurtada é apresentada como um link clicável, construído anexando o caminho encurtado ao nome do host, ambos inseridos dinamicamente usando a sintaxe de template do Flask.
    • A coluna "Clicks" mostra quantas vezes a URL encurtada foi acessada, com o texto centralizado para maior clareza.
    • A coluna "Info" fornece um link para análises detalhadas para cada URL, usando a função url_for do Flask para gerar a URL dinamicamente e um ícone (<i class="material-icons">info_outline</i>) para representação visual.

Este template de resultados de pesquisa aprimora o serviço "Shorty", permitindo que os usuários encontrem e gerenciem efetivamente URLs com base em tags, proporcionando uma experiência de usuário perfeita e intuitiva. O uso consistente de estilos e elementos de layout da página de índice garante um design coeso em toda a aplicação.

✨ Verificar Solução e Praticar

Criar o Template da Página de Análise

A página de análise exibirá informações detalhadas sobre o uso de uma URL curta, incluindo cliques, navegador e estatísticas de plataforma.

Em templates/data.html, adicione o seguinte código HTML:

<!doctype html>
<html>
  <head>
    <title>Shorty</title>

    <!-- Add Local SVG image when hosting. -->
    <link
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet"
    />

    <link rel="stylesheet" type="text/css" href="../static/skeleton.css" />
    <link rel="stylesheet" type="text/css" href="../static/normalize.css" />
    <link rel="stylesheet" type="text/css" href="../static/main.css" />
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,700,900"
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="container  main_header">
      <h3 align="left"><a href="{{url_for('index')}}">Shorty</a></h3>
      <p>A dead simple URL shortener service.</p>
    </div>
    <div class=" container modal-content">
      <!-- Array index -> 
      broswer : 
          CHROME ,
          FIREFOX,
          SAFARI,
          OTHER_BROWSER,
      platform:
          ANDROID,
          IOS,
          WINDOWS,
          LINUX ,
          MAC,
          OTHER_PLATFORM
       -->
      <div class="url_info">
        <h4>
          Analytics data for :
          <a href="{{host+info[1]}}">{{'localhost/'+info[1]}}</a>
        </h4>
        <p>
          Original URL :
          <a style="text-decoration: none" href="{{info[0]}}">{{info[0]}}</a>
        </p>
      </div>
      <div class="data_block">
        <div class="browser_list">
          <h4>Browser</h4>
          <table>
            <thead>
              <tr>
                <th>Chrome</th>
                <th>Firefox</th>
                <th>Safari</th>
                <th>Other Broswers</th>
              </tr>
            </thead>

            <tbody>
              <tr>
                <td style="padding-left: 5px;">{{browser[0]}}</td>
                <td>{{browser[1]}}</td>
                <td>{{browser[2]}}</td>
                <td>{{browser[3]}}</td>
              </tr>
            </tbody>
          </table>
        </div>
        <div class="platform_list">
          <h4>Platform</h4>
          <table>
            <thead>
              <tr>
                <th>Android</th>
                <th>IOS</th>
                <th>Windows</th>
                <th>Linux</th>
                <th>Mac</th>
                <th>Other Platforms</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td style="padding-left: 5px;">{{platform[0]}}</td>
                <td>{{platform[1]}}</td>
                <td>{{platform[2]}}</td>
                <td>{{platform[3]}}</td>
                <td>{{platform[4]}}</td>
                <td>{{platform[5]}}</td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
    </div>
  </body>
</html>

Este código inclui informações sobre o número de cliques, uso do navegador e distribuição da plataforma. Aqui está uma análise de sua estrutura e componentes:

  • Uma div com as classes container modal-content encapsula as informações de análise, estilizadas como um modal ou um bloco de conteúdo distinto dentro da página.
  • A url_info div apresenta:
    • Um cabeçalho <h4> indicando que os dados a seguir pertencem à análise de uma URL curta específica. A URL encurtada é exibida como um link clicável, construído usando as variáveis host e info[1], onde info[1] contém o caminho encurtado.
    • Um parágrafo (<p>) mostrando a URL original como um link clicável, facilitando o acesso ao conteúdo original.
  • Duas seções separadas, browser_list e platform_list, cada uma contendo uma tabela exibindo as estatísticas de uso para navegadores e plataformas, respectivamente:
    • A seção browser_list inclui uma tabela com cabeçalhos para Chrome, Firefox, Safari e Outros Navegadores. A seção <tbody> exibe as estatísticas correspondentes, que são extraídas da variável de array browser passada para o template.
    • Da mesma forma, a seção platform_list tem uma tabela para uso da plataforma, com cabeçalhos para Android, iOS, Windows, Linux, Mac e Outras Plataformas. As estatísticas de uso são mostradas no corpo da tabela, originadas da variável de array platform.
  • As tabelas usam <thead> para cabeçalhos e <tbody> para os dados reais, garantindo HTML semântico e facilitando a estilização e acessibilidade.
  • Células de dados (<td>) dentro das tabelas exibem as contagens respectivas para cada navegador e plataforma, alinhadas e estilizadas para legibilidade.

Este template comunica efetivamente os dados de análise ao usuário, oferecendo insights sobre como a URL encurtada está sendo acessada, incluindo os navegadores e plataformas usados pelo público. O layout limpo, combinado com a clara separação de dados em seções distintas, facilita a compreensão e interpretação do desempenho da URL pelos usuários.

✨ Verificar Solução e Praticar

Criar o Template da Página 404

Uma página 404 personalizada melhora a experiência do usuário, fornecendo uma mensagem de erro mais útil quando uma URL curta não é encontrada.

Em templates/404.html, adicione o seguinte código HTML:

<!doctype html>
<html>
  <head>
    <title>Shorty</title>

    <!-- Add Local SVG image when hosting. -->
    <link
      href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet"
    />

    <link rel="stylesheet" type="text/css" href="../static/skeleton.css" />
    <link rel="stylesheet" type="text/css" href="../static/normalize.css" />
    <link rel="stylesheet" type="text/css" href="../static/main.css" />
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,700,900"
      rel="stylesheet"
    />
  </head>
  <body>
    <div class="lost">
      <h2>Oi , chap you seem lost !</h2>
    </div>
  </body>
</html>

Este template de página 404 personalizado comunica efetivamente aos usuários que a página que eles estão procurando não existe, mantendo um tom leve.

✨ Verificar Solução e Praticar

Design da Interface Web

Em seguida, projetaremos a interface web. Comece criando o arquivo CSS principal para estilizar nossa aplicação.

Em static/main.css, adicione o seguinte código CSS para estilizar os elementos HTML:

html {
  border-top: 5px solid #d9edf7;
}
body {
  font-family: "Roboto", sans-serif;
  margin-top: 50px;
  margin-bottom: 0;
}
h3 {
  padding: 0;
  margin: 0;
}
h3 a {
  font-weight: 700;
  text-decoration: none;
  color: black;
}
h3 a:hover {
  color: grey;
  transition: 0.2s all;
}
/** Main Header */
.main_header {
  margin-bottom: 20px;
}
/* Search Block */
.search_url_block {
  padding: 15px;
  background-color: #d9edf7;
  color: #31708f;
  border-radius: 5px;
  margin-bottom: 10px;
}
form {
  margin: 0;
}

.search_header {
  margin-top: 20px;
}

.material-icons {
  padding: 5px;
  padding-top: 7px;
  opacity: 0.7;
}

.material-icons:hover {
  opacity: 1;
}
/* Gen URL block */

.gen_block {
  margin-top: 10px;
  padding: 15px;
  background-color: #dff0d8;
  color: #2b542c;
  border-radius: 5px;
  width: auto;
  font-size: 20px;
}
/* Error Disp */
.error_disp {
  padding: 15px;
  border-radius: 5px;
  background-color: #fcf8e3;
  color: #b84442;
  width: auto;
  font-size: 20px;
  margin-top: 10px;
}

/* Table Display Block*/

.table_list {
  padding-top: 10px;
  margin-top: 40px;
  border-top: 2px solid lightgrey;
}
table {
  font-size: 20px;
  width: 100%;
}
thead {
  font-weight: 700;
  padding: 2px;
}
tbody {
  font-weight: 400;
}
th {
  padding: 5px;
}
td {
  padding: 5px;
}
tr {
  padding: 5px;
}
tbody tr:hover {
  background-color: #f5f5f5;
  transition: 0.1s all ease-out;
}

/* Analytics block*/
.url_info {
  margin-top: 10px;
  padding: 15px;
  background-color: #d9edf7;
  color: #31708f;
  border-radius: 5px;
  margin-bottom: 10px;
}
.url_info h4,
p {
  margin: 0;
  padding: 0;
}
.data_block {
  margin-top: 20px;
}

/* 404 . Lost*/
.lost {
  margin-top: 20px;
}
.lost h2 {
  font-weight: 700;
  font-size: 40px;
  text-align: center;

  color: #31708f;
}
.lost p {
  font-weight: 400;
  font-size: 20px;
  text-align: center;
}

O design geral usa uma combinação de cores de fundo, cores de texto e preenchimento para criar uma interface limpa e moderna que é fácil de navegar. O uso de border-radius em vários elementos dá à interface uma sensação mais suave e acessível, enquanto os efeitos de hover aprimoram a interatividade. O uso consistente da fonte Roboto mantém uma aparência coesa em toda a aplicação.

✨ Verificar Solução e Praticar

Conexão com o Banco de Dados e Funções de Operação

Funções utilitárias lidarão com conexões de banco de dados, validações de URL, atualização de contadores de navegador e plataforma, e geração de tokens aleatórios para URLs curtas.

Conexão com o Banco de Dados

Primeiro, você configurará a conexão com o banco de dados usando pymysql. Isso é crucial para permitir que sua aplicação Flask interaja com o banco de dados MySQL.

Em utils.py, adicione o seguinte código Python:

from urllib.parse import urlparse
import random
import string

import pymysql


db_config = {
    "host": "localhost",
    "user": "root",
    "password": "",
    "db": "SHORTY"
}


def get_db_connection() -> pymysql.Connection:
    """Create and return a new database connection."""
    return pymysql.connect(**db_config)
  • A biblioteca pymysql é usada para conectar ao banco de dados MySQL. Esta biblioteca permite que aplicações Python interajam com bancos de dados MySQL usando uma API simples.
  • O dicionário db_config contém parâmetros de conexão com o banco de dados, como host, usuário, senha e nome do banco de dados. Estes são importados de um módulo config separado, presumivelmente para melhor segurança e modularidade. Manter as configurações separadas permite ajustes mais fáceis sem modificar o código base principal.
  • A função get_db_connection() cria e retorna uma nova conexão com o banco de dados usando a função pymysql.connect(**db_config). A sintaxe **db_config é usada para desempacotar o dicionário em argumentos de palavra-chave.

Funções de Operação do Banco de Dados

Após estabelecer uma conexão com o banco de dados, a próxima etapa envolve a criação de funções que realizam operações no banco de dados. Isso inclui listar dados para uma determinada URL curta e atualizar contadores com base no uso do navegador e da plataforma.

Em utils.py, adicione o seguinte código Python:

def list_data(shorty_url: str) -> tuple:
    """
    Takes short_url for input.
    Returns counter , browser , platform ticks.
    """
    with get_db_connection() as conn, conn.cursor() as cursor:

        su = [shorty_url]
        info_sql = "SELECT URL , S_URL ,TAG FROM WEB_URL WHERE S_URL= %s; "
        counter_sql = "SELECT COUNTER FROM WEB_URL WHERE S_URL= %s; "
        browser_sql = "SELECT CHROME , FIREFOX , SAFARI, OTHER_BROWSER FROM WEB_URL WHERE S_URL =%s;"
        platform_sql = "SELECT ANDROID , IOS , WINDOWS, LINUX , MAC , OTHER_PLATFORM FROM WEB_URL WHERE S_URL = %s;"

        cursor.execute(info_sql, su)
        info_fetch = cursor.fetchone()
        cursor.execute(counter_sql, su)
        counter_fetch = cursor.fetchone()
        cursor.execute(browser_sql, su)
        browser_fetch = cursor.fetchone()
        cursor.execute(platform_sql, su)
        platform_fetch = cursor.fetchone()

    return info_fetch, counter_fetch, browser_fetch, platform_fetch

def update_counters(cursor: pymysql.Connection, short_url: str, browser_dict: dict, platform_dict: dict) -> None:
    """Update browser and platform counters in the database for the given short_url."""
    counter_sql = """UPDATE WEB_URL SET COUNTER = COUNTER + 1,
                     CHROME = CHROME + %s, FIREFOX = FIREFOX + %s, SAFARI = SAFARI + %s, OTHER_BROWSER = OTHER_BROWSER + %s,
                     ANDROID = ANDROID + %s, IOS = IOS + %s, WINDOWS = WINDOWS + %s, LINUX = LINUX + %s, MAC = MAC + %s, OTHER_PLATFORM = OTHER_PLATFORM + %s
                     WHERE S_URL = %s;"""
    cursor.execute(counter_sql, (browser_dict['chrome'], browser_dict['firefox'], browser_dict['safari'], browser_dict['other'],
                                 platform_dict['android'], platform_dict['iphone'], platform_dict[
                                     'windows'], platform_dict['linux'], platform_dict['macos'], platform_dict['other'],
                                 short_url))
  • A função list_data(shorty_url) foi projetada para recuperar várias informações da tabela WEB_URL para uma determinada URL curta (shorty_url). Ela estabelece uma conexão com o banco de dados e executa quatro consultas SQL para buscar a URL original, a tag associada, o contador de acesso, o navegador e as análises da plataforma. Cada consulta é executada separadamente, e os resultados são buscados e retornados.
  • A função update_counters(cursor, short_url, browser_dict, platform_dict) atualiza o contador de acesso, o navegador e as contagens da plataforma para uma determinada URL curta no banco de dados. Esta função recebe um cursor do banco de dados, a URL curta e dois dicionários contendo contagens para cada navegador e plataforma como argumentos. Ela constrói uma instrução SQL UPDATE para incrementar os contadores para a URL curta com base nos dados fornecidos. A função assume que as informações do navegador e da plataforma foram determinadas antes de chamar esta função, e que essas informações são passadas como dicionários (browser_dict e platform_dict), com chaves correspondentes às colunas na tabela WEB_URL.

Esta configuração é um padrão típico para aplicações web usando Flask e MySQL, onde funções utilitárias são definidas para operações comuns de banco de dados. Essas funções podem então ser importadas e usadas em toda a aplicação para interagir com o banco de dados, abstraindo o acesso direto ao banco de dados e as consultas SQL da lógica principal da aplicação.

✨ Verificar Solução e Praticar

Implementar Funções Utilitárias Não Relacionadas ao Banco de Dados

Por fim, implemente funções utilitárias que não interagem com o banco de dados. Isso inclui a geração de tokens aleatórios para URLs curtas e a validação de URLs.

Em utils.py, adicione o seguinte código Python:

def random_token(size: int = 6) -> str:
    """
    Generates a random string of 6 chars , use size argument
    to change the size of token.
    Returns a valid token of desired size ,
    *default is 6 chars
    """
    BASE_LIST = string.digits + string.ascii_letters

    token = ''.join((random.choice(BASE_LIST)) for char in range(size))
    return token


def url_check(url: str) -> bool:
    """
    Expects a string as argument.
    Retruns True , if URL is valid else False.
    For detailed docs look into urlparse.
    """
    try:
        result = urlparse(url)
        if all([result.scheme, result.netloc]):
            return True
        else:
            return False
    except:
        return False
  • A função random_token gera uma string aleatória, que serve como um token para criar URLs curtas. Por padrão, ela cria um token de 6 caracteres, mas pode ser ajustada com o argumento size.
    • Ela usa uma combinação de dígitos (string.digits) e letras (string.ascii_letters) como a lista base para gerar o token.
    • O token é gerado selecionando aleatoriamente caracteres da BASE_LIST pelo número de vezes especificado pelo parâmetro size. Isso é feito usando uma list comprehension e random.choice(), que seleciona um elemento aleatório da sequência especificada.
    • O token gerado é então retornado como uma string. Este token pode ser usado como o identificador da URL curta.
  • A função url_check valida uma determinada URL para garantir que ela esteja em um formato adequado.
    • Ela usa a função urlparse do módulo urllib.parse para analisar a URL fornecida em componentes.
    • A função verifica se a URL possui um esquema (como http, https) e um netloc (localização de rede, por exemplo, www.example.com). Ambos são componentes essenciais para que uma URL seja considerada válida.
    • Se ambos os componentes estiverem presentes, a função retorna True, indicando que a URL é válida. Se um deles estiver ausente, ou se ocorrer uma exceção durante a análise (por exemplo, se a entrada não for uma string), a função retorna False.
    • Essa validação é importante para garantir que apenas URLs válidas sejam processadas e armazenadas pela aplicação.

Essas funções utilitárias são integrais ao serviço de encurtamento de URL, fornecendo capacidades essenciais para gerar identificadores únicos para URLs encurtadas e garantir que apenas URLs válidas sejam aceitas pelo sistema.

✨ Verificar Solução e Praticar

Inicializar e Implementar a Rota Index

Finalmente, construiremos o núcleo do nosso encurtador de URLs — a aplicação Flask.

Comece configurando a rota index. Esta rota servirá a página principal e lidará com requisições GET e POST. Em uma requisição GET, ela exibe todas as URLs encurtadas. Em uma requisição POST, ela aceita uma nova URL para encurtar, gera um token único e o salva no banco de dados.

Em app.py, adicione o seguinte código Python:

from flask import Flask, request, redirect, render_template, make_response

from utils import get_db_connection, list_data, random_token, update_counters, url_check


app = Flask(__name__)


@app.route('/', methods=['GET', 'POST'])
def index():
    with get_db_connection() as conn, conn.cursor() as cursor:
        ## Fetch all data to display on index
        cursor.execute("SELECT * FROM WEB_URL;")
        result_all_fetch = cursor.fetchall()

        if request.method == 'POST':
            og_url = request.form.get('url_input')
            custom_suff = request.form.get('url_custom', '')
            tag_url = request.form.get('url_tag', '')

            token_string = random_token() if not custom_suff else custom_suff

            if og_url and url_check(og_url):
                cursor.execute(
                    "SELECT S_URL FROM WEB_URL WHERE S_URL = %s FOR UPDATE", (token_string,))
                if cursor.fetchone() is None:
                    cursor.execute(
                        "INSERT INTO WEB_URL(URL, S_URL, TAG) VALUES(%s, %s, %s)", (og_url, token_string, tag_url))
                    conn.commit()
                    return render_template('index.html', shorty_url=f"{shorty_host}{token_string}")
                else:
                    error = "The custom suffix already exists. Please use another suffix or leave it blank for a random one."
            else:
                error = "Invalid URL provided. Please enter a valid URL."

            return render_template('index.html', table=result_all_fetch, host=shorty_host, error=error)

        return render_template('index.html', table=result_all_fetch, host=shorty_host)

A função index dentro de app.py configura a funcionalidade principal do serviço de encurtamento de URL usando Flask, um micro framework web escrito em Python. Esta função define como a rota index (/) da aplicação se comporta e processa requisições GET e POST. Aqui está uma explicação detalhada do código:

Configuração do Flask

  • A aplicação Flask é inicializada com app = Flask(__name__).
  • O decorador @app.route('/', methods=['GET', 'POST']) especifica que a função index lida com requisições para a URL raiz (/) e aceita os métodos GET e POST.

Tratamento de Requisições GET

  • Quando a função recebe uma requisição GET, ela se conecta ao banco de dados usando a função utilitária get_db_connection() e busca todos os registros da tabela WEB_URL. Isso serve para exibir todas as URLs encurtadas na página index.
  • Os registros buscados são passados para a função render_template, juntamente com a URL do host (shorty_host), para renderizar o template index.html. Este template provavelmente inclui uma tabela ou lista para exibir cada URL encurtada e seus detalhes.

Tratamento de Requisições POST

  • Para requisições POST, tipicamente enviadas a partir de um formulário na página index, a função extrai a URL original (og_url), um sufixo personalizado opcional (custom_suff) e uma tag opcional (tag_url) dos dados do formulário.
  • Em seguida, ela gera um token aleatório para a URL encurtada usando random_token(), a menos que um sufixo personalizado seja fornecido. Este token (ou sufixo personalizado) serve como o identificador único para a URL encurtada.
  • Antes de prosseguir, a função valida a URL original usando url_check(og_url). Se a URL for válida e o token/sufixo for único (não estiver já no banco de dados), um novo registro é inserido na tabela WEB_URL com a URL original, o token/sufixo como a URL curta e a tag.
  • Se a operação for bem-sucedida, a função renderiza novamente o template index.html, exibindo a URL recém-encurtada (shorty_url) juntamente com todos os registros existentes.
  • Se o token/sufixo já existir no banco de dados ou a URL original for inválida, uma mensagem de erro é definida, e o template index.html é renderizado com a mensagem de erro e os registros existentes.

Tratamento de Erros e Renderização de Templates

  • A função render_template é usada extensivamente para renderizar o template index.html, passando vários parâmetros como a lista de todos os registros (table), a URL base do host para os links encurtados (host), a URL recém-encurtada (shorty_url) e quaisquer mensagens de erro (error). Esta função facilita a renderização de conteúdo dinâmico no Flask, interpolando variáveis Python em templates HTML.

Esta aplicação Flask serve como o backend para o serviço de encurtamento de URL, lidando com interações com o banco de dados, validação de URL e geração de tokens, ao mesmo tempo em que gera dinamicamente páginas web com base nas interações do usuário e no conteúdo do banco de dados.

✨ Verificar Solução e Praticar

Implementar a Rota de Redirecionamento e a Rota de Análise

Rota de Redirecionamento

Em seguida, crie uma rota para lidar com o redirecionamento de uma URL curta para a URL original. Esta rota captura qualquer URL curta, procura-a no banco de dados e redireciona o usuário para a URL original.

Adicione o seguinte código a app.py:

@app.route('/<short_url>')
def reroute(short_url):
    with get_db_connection() as conn, conn.cursor() as cursor:
        platform = request.user_agent.platform or 'other'
        browser = request.user_agent.browser or 'other'
        browser_dict = {'firefox': 0, 'chrome': 0, 'safari': 0, 'other': 0}
        platform_dict = {'windows': 0, 'iphone': 0,
                         'android': 0, 'linux': 0, 'macos': 0, 'other': 0}

        ## Increment browser and platform counters
        browser_dict[browser] = browser_dict.get(browser, 0) + 1
        platform_dict[platform] = platform_dict.get(platform, 0) + 1

        cursor.execute(
            "SELECT URL FROM WEB_URL WHERE S_URL = %s;", (short_url,))
        try:
            new_url = cursor.fetchone()[0]
            update_counters(cursor, short_url, browser_dict, platform_dict)
            conn.commit()
            return redirect(new_url)
        except Exception:
            return render_template('404.html'), 404
  • O decorador @app.route('/<short_url>') cria uma rota dinâmica que corresponde a qualquer segmento de caminho que segue a URL raiz. Este segmento (short_url) é passado para a função reroute como um argumento.
  • Dentro da função, ela estabelece uma conexão com o banco de dados e inicializa dicionários para rastrear o navegador e a plataforma de onde a requisição se originou. request.user_agent do Flask é usado para determinar o navegador e a plataforma.
  • Em seguida, ela executa uma consulta SQL para encontrar a URL original associada à short_url fornecida. Se encontrada, ela atualiza os contadores para o navegador e a plataforma no banco de dados usando a função update_counters.
  • Após confirmar as alterações no banco de dados, a função usa a função redirect do Flask para enviar o usuário para a URL original.
  • Se a short_url não for encontrada no banco de dados, ou qualquer outra exceção ocorrer, a função renderiza uma página de erro 404 usando render_template('404.html').

Rota de Análise

Crie uma rota de análise que exibe informações detalhadas sobre uma URL curta específica, como o número de vezes que foi acessada e de quais plataformas e navegadores.

Adicione o seguinte código a app.py:

@app.route('/analytics/<short_url>')
def analytics(short_url):
    info_fetch, counter_fetch, browser_fetch, platform_fetch = list_data(
        short_url)
    return render_template("data.html", host=shorty_host, info=info_fetch, counter=counter_fetch, browser=browser_fetch, platform=platform_fetch)
  • O decorador @app.route('/analytics/<short_url>') define uma rota para acessar análises sobre uma URL curta específica. A short_url é capturada do caminho da URL e passada para a função analytics.
  • A função chama list_data(short_url), que consulta o banco de dados em busca de informações sobre a URL curta, incluindo o número de vezes que ela foi acessada e a distribuição de acesso em diferentes navegadores e plataformas.
  • Os dados buscados (info_fetch, counter_fetch, browser_fetch, platform_fetch) são então passados para a função render_template juntamente com a URL do host (shorty_host) para renderizar o template data.html. Este template provavelmente apresenta os dados de análise em um formato amigável ao usuário, como tabelas ou gráficos.

Essas rotas expandem a funcionalidade do serviço de encurtamento de URL, permitindo que ele não apenas redirecione os usuários de URLs curtas para seus destinos originais, mas também forneça informações sobre como essas URLs curtas estão sendo usadas, incluindo contagens de acesso e os tipos de dispositivos e navegadores de onde os links são acessados. Essa informação pode ser valiosa para entender o alcance e o impacto das URLs compartilhadas.

✨ Verificar Solução e Praticar

Implementar a Rota de Pesquisa e Executar a Aplicação

Rota de Pesquisa

Configure uma rota de pesquisa para permitir que os usuários encontrem URLs encurtadas por tags. Esta rota lida com requisições GET e POST, exibindo um formulário de pesquisa e processando consultas de pesquisa, respectivamente.

Adicione o seguinte código a app.py:

@app.route('/search', methods=['GET', 'POST'])
def search():
    s_tag = request.form.get('search_url', '')
    if not s_tag:
        return render_template('index.html', error="Please enter a search term.")

    with get_db_connection() as conn, conn.cursor() as cursor:
        cursor.execute("SELECT * FROM WEB_URL WHERE TAG = %s", (s_tag,))
        search_tag_fetch = cursor.fetchall()
        return render_template('search.html', host=shorty_host, search_tag=s_tag, table=search_tag_fetch)
  • O decorador @app.route('/search', methods=['GET', 'POST']) configura a rota em /search, lidando com requisições GET e POST. Enquanto a requisição GET pode ser usada para exibir um formulário de pesquisa, a requisição POST processa os dados do formulário enviados pelos usuários.
  • Dentro da função search, request.form.get('search_url', '') tenta recuperar o termo de pesquisa dos dados do formulário enviados. O segundo parâmetro ('') é o valor padrão se 'search_url' não for encontrado, efetivamente tornando o termo de pesquisa uma string vazia nesses casos.
  • Se nenhum termo de pesquisa for fornecido (not s_tag), a função redireciona o usuário para a página inicial com uma mensagem de erro indicando que um termo de pesquisa é necessário.
  • Se um termo de pesquisa for fornecido, a função conecta-se ao banco de dados e executa uma consulta SQL para encontrar todos os registros na tabela WEB_URL onde a coluna TAG corresponde ao termo de pesquisa fornecido. Isso permite que os usuários encontrem todas as URLs encurtadas associadas a uma tag específica.
  • Os resultados desta consulta (search_tag_fetch) são então passados para a função render_template, juntamente com a URL do host (shorty_host) e o termo de pesquisa (s_tag), para renderizar o template search.html. Este template provavelmente exibe os resultados em uma lista ou formato de tabela, permitindo que os usuários vejam todos os registros correspondentes e possivelmente interajam com eles (por exemplo, visitar as URLs originais, visualizar análises).

Executar a Aplicação

Finalmente, adicione o código para executar sua aplicação Flask. Isso inclui definir o host e a porta para a aplicação ouvir, bem como especificar as variáveis de ambiente.

Adicione o seguinte código ao final de app.py:

shorty_host = "https://****.labex.io/"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

Nota: Você deve substituir a URL em shorty_host pela URL do ambiente atual. Você pode encontrá-la mudando para a aba Web 8080, e a URL deve terminar com /.

Web 8080 tab URL

Agora, você pode executar o projeto usando o seguinte comando:

python app.py

Mude para a aba "Web 8080" e recarregue a página web para ver os seguintes efeitos.

Converter a URL com/sem sufixo personalizado, pesquisar URLs por tag, acessar o link:

Visualizar informações sobre o sistema operacional e a plataforma usados para acessar o link:

✨ Verificar Solução e Praticar

Resumo

Parabéns por concluir o projeto de encurtador de URLs! Esta ferramenta simplifica o compartilhamento de URLs longas, criando links mais curtos e gerenciáveis. No entanto, há algumas considerações importantes a serem lembradas:

  1. Comprimento da URL Base: Se a URL base do próprio encurtador for longa, as URLs encurtadas resultantes podem não ser tão curtas quanto o esperado (como no projeto). O comprimento total da URL encurtada inclui a URL base, o que pode limitar a eficácia do encurtador. Para obter as URLs mais concisas, considere usar uma URL base ou nome de domínio mais curto para o seu serviço.

  2. Restrições de Incorporação de Websites: Você pode encontrar problemas como "Refused to display 'https://scholar.google.com/' in a frame because it set 'X-Frame-Options' to 'sameorigin'." Este erro ocorre porque alguns websites usam o cabeçalho HTTP X-Frame-Options para impedir que seu conteúdo seja exibido em iframes em outros domínios, aprimorando a segurança contra ataques de "clickjacking". Quando um site define este cabeçalho como sameorigin, ele restringe a incorporação a iframes que compartilham a mesma origem. Esta não é uma limitação do encurtador de URLs, mas uma medida de segurança implementada pelo website de destino. Para um redirecionamento perfeito, é melhor usar as URLs encurtadas como links diretos, em vez de incorporá-las em iframes.

Essas considerações destacam o equilíbrio entre conveniência e segurança no desenvolvimento web e a importância da conscientização do usuário para o uso ideal da ferramenta.