O Tornado é um framework web assíncrono de alta performance escrito em Python. Ele permite que desenvolvedores construam aplicações web escaláveis, flexíveis e com suporte a milhares de conexões simultâneas. Além disso, o Tornado é ideal para aplicações que exigem manipulação de eventos em tempo real, como chats e notificações push.
Neste artigo, vamos explorar os principais recursos do Tornado e como usá-los para construir aplicações web modernas e escaláveis.
Configuração do ambiente de desenvolvimento do Tornado
Antes de começar a trabalhar com o Tornado, é necessário configurar o ambiente de desenvolvimento. Para isso, é necessário instalar o Python e o Tornado usando o gerenciador de pacotes pip. Abra o terminal e execute o seguinte comando:
pip install tornado
Depois de instalar o Tornado, você pode verificar se a instalação foi bem-sucedida importando-o no interpretador Python:
import tornado
Se não ocorrerem erros, a instalação foi bem-sucedida.
Como criar um aplicativo web básico usando o Tornado
Vamos começar criando um aplicativo web básico usando o Tornado. O primeiro passo é importar o módulo tornado.ioloop e criar um objeto IOLoop:
import tornado.ioloop
if __name__ == "__main__":
tornado.ioloop.IOLoop.current().start()
Em seguida, vamos criar uma classe chamada MainHandler que herda de tornado.web.RequestHandler. Essa classe é responsável por manipular as requisições HTTP feitas para o aplicativo:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Olá, mundo")
if __name__ == "__main__":
app = tornado.web.Application([(r"/", MainHandler)])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Nesse exemplo, a classe MainHandler recebe as requisições GET feitas para a rota “/” e responde com a string “Olá, mundo“. O objeto Application é usado para agrupar as rotas do aplicativo e o método listen é usado para iniciar o servidor HTTP na porta 8888.
Trabalhando com rotas e manipuladores em Tornado
O Tornado usa um sistema de rotas para mapear as requisições HTTP para os manipuladores correspondentes. Cada rota é definida usando uma expressão regular que especifica o padrão de URL e um manipulador que processa a requisição. Veja um exemplo:
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Olá, mundo")
class AboutHandler(tornado.web.RequestHandler):
def get(self):
self.write("Sobre nós")
if __name__ == "__main__":
app = tornado.web.Application([(r"/", MainHandler), (r"/about", AboutHandler)])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Nesse exemplo, definimos duas rotas: uma para a raiz do aplicativo e outra para a página “Sobre nós“. Ambas as rotas são manipuladas por classes distintas: MainHandler e AboutHandler.
Como integrar bancos de dados com o Tornado
O Tornado oferece suporte a uma variedade de bancos de dados, incluindo MySQL, PostgreSQL, MongoDB e Redis. Para usar um banco de dados em seu aplicativo Tornado, você deve primeiro instalar o driver correspondente usando o pip. Por exemplo, para instalar o driver do MySQL, você pode executar o seguinte comando:
pip install mysql-connector-python
Em seguida, você pode se conectar ao banco de dados e executar consultas SQL usando o módulo tornado.gen. Veja um exemplo:
import tornado.ioloop
import tornado.web
import tornado.gen
import mysql.connector
class MainHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
conn = mysql.connector.connect(user='root', password='senha', host='127.0.0.1', database='mydatabase')
cursor = conn.cursor()
cursor.execute("SELECT * FROM mytable")
result = cursor.fetchall()
self.write(str(result))
conn.close()
if __name__ == "__main__":
app = tornado.web.Application([(r"/", MainHandler)])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Nesse exemplo, usamos o módulo tornado.gen para executar a consulta SQL assincronamente. A função coroutine indica que a função get é assíncrona e que pode pausar a execução para esperar a conclusão de operações de entrada/saída.
Autenticação e autorização em Tornado
O Tornado oferece suporte a diferentes esquemas de autenticação, incluindo Basic Auth, Digest Auth, OAuth e JWT. Você pode usar esses esquemas para proteger recursos do aplicativo e controlar o acesso de usuários e serviços externos.
Por exemplo, para usar a autenticação Basic Auth, você pode adicionar um método prepare na classe do manipulador e verificar as credenciais do usuário a cada requisição:
import tornado.ioloop
import tornado.web
import base64
class MainHandler(tornado.web.RequestHandler):
def prepare(self):
auth_header = self.request.headers.get('Authorization')
if auth_header:
auth_decoded = base64.b64decode(auth_header.split()[1]).decode('utf-8')
username, password = auth_decoded.split(':')
if username == 'admin' and password == 'secret':
return
self.set_status(401)
self.set_header('WWW-Authenticate', 'Basic realm=Restricted')
def get(self):
self.write("Página protegida")
if __name__ == "__main__":
app = tornado.web.Application([(r"/", MainHandler)])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Nesse exemplo, usamos o método prepare para verificar se as credenciais de autenticação estão presentes na requisição. Se as credenciais estiverem corretas, a requisição é processada normalmente. Caso contrário, a resposta HTTP 401 Unauthorized é enviada ao cliente.
Implementando recursos assíncronos com Tornado
O Tornado é conhecido por sua capacidade de suportar operações assíncronas de entrada/saída, o que significa que ele pode lidar com milhares de conexões simultâneas sem bloquear o thread principal. Para aproveitar essa capacidade, é importante usar a função coroutine do Tornado e outras ferramentas de programação assíncrona do Python.
Por exemplo, para lidar com uma solicitação assíncrona de I/O em uma chamada de API, podemos usar o método gen.coroutine e a função yield, como mostra o exemplo abaixo:
import tornado.ioloop
import tornado.web
import tornado.gen
import requests
class AsyncHandler(tornado.web.RequestHandler):
@tornado.gen.coroutine
def get(self):
response = yield tornado.gen.Task(requests.get, 'https://www.example.com')
self.write(response.text)
if __name__ == "__main__":
app = tornado.web.Application([(r"/", AsyncHandler)])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
Neste exemplo, a chamada de API é tratada assincronamente, sem bloquear o thread principal, usando a função coroutine e a função yield para esperar a resposta do servidor.
Conclusão
O Tornado é um framework Python leve e de alto desempenho para desenvolvimento de aplicações web, que oferece suporte a programação assíncrona e é amplamente usado em aplicações de grande escala. Ele oferece várias funcionalidades para lidar com operações de entrada/saída assíncronas, além de suportar diferentes esquemas de autenticação e integração com bancos de dados. Com sua arquitetura assíncrona, ele é uma escolha ideal para construir aplicativos escaláveis e de alta performance.
Referências
- Documentação oficial do Tornado: https://www.tornadoweb.org/en/stable/
- Guia de introdução ao Tornado: https://realpython.com/python-web-applications-with-tornado/
- Tutorial de programação assíncrona com Tornado: https://www.twilio.com/blog/asynchronous-http-requests-in-python-with-tornado
- Exemplo de uso do Tornado com MongoDB: https://medium.com/@cris_ludwig/integrating-tornado-mongodb-async-c020610f16af