lazywf: o framework web rápido para o desenvolvedor preguiçoso
Porque programador bom é programador preguiçoso.
Como já disse antes, selecionar pessoas para trabalhar comigo é uma atividade até bem frequente para mim. E uma das coisas que eu gosto de ver em desenvolvedores é a preguiça.
A preguiça faz com que um desenvolvedor jamais entre num processo extremamente repetitivo sem sair disso com algum script para automação do mesmo. Ela faz com que tarefas complicadas tornem-se simples porque o desenvolvedor preguiçoso se recusa a girar muitas manivelas se ele pode simplesmente apertar um botão.
Eu mesmo sou um desenvolvedor preguiçoso. E como de quando em quando surge a necessidade de configurar mui rapidamente uma API bem simples com um mínimo de validação, eu comecei a perceber que o Django, minha ferramenta-padrão para esse tipo de coisa acaba sendo mais complexa do que o necessário. Dependendo da simplicidade da tarefa, ele mostra-se um canhão a ser usado para matar uma mosca.
Por isso criei o lazywf
: o framework web para gente preguiçosa.
Enquanto no Django você tem que criar o projeto, configurar direito o settings.py
, escrever os modelos, criar as migrações, migrar o banco, encontrar algum framework de REST, instalá-lo, escrever serializadores ou algum tipo de view especial e só depois conseguir ter qualquer coisa minimamente usável, com o lazywf
a coisa toda se resume, basicamente, a herdar uma classe, definir um mínimo de validação para seus modelos e pronto.
Um exemplo
Digamos que eu queira criar uma API para lidar com minha lista de projetos no Github. Simplesmente quero manter salvos no banco de dados o nome do projeto e a URL para o git clone
do mesmo.
1- Direto ao ponto: modelar
Na raiz do projeto, descrevemos um pouco do nosso modelo principal no arquivo models.yaml
:
projects:
constraints:
keys: [user, name]
unique: [user, name]
validations:
user:
type: string
required: true
name:
type: string
required: true
URL:
type: string
required: true
maxlength: 256
minlength: 8
2- Criar um server
O lazywf
bem que poderia prover meramente um comando tipo lazywf
que, sendo executado em um diretório contendo um models.yaml
já poderiar criar uma API REST usável. Entretanto, como eu sei bem que todo código que escrevemos acaba precisando ser estendido de alguma forma, preferi obrigar o usuário a escrever estas poucas linhas, já que acaba sendo benéfico para ele manter uma base de código mínima.
Eis o server.py
:
#!env python3from lazywf import TheLaziestWebFrameworkEVER
class Lazy(TheLaziestWebFrameworkEVER):
pass
Lazy().run()
3- Rodar
# python3 server.py
Você pode passar como argumento de linha de comando a porta em que deseja que o servidor ouça. Por padrão é a 8080
.
Servindo páginas
Caso queira servir algumas páginas, basta adicionar um método para cada uma e a rota correspondente:
#!env python3
from lazywf import TheLaziestWebFrameworkEVER
class Lazy(TheLaziestWebFrameworkEVER):
def create_routes(self):
self.add_route(‘/’, ‘GET’, self.index)
def index(self):
return self.render(‘index.html’)
Lazy().run()
O método render
do server pode receber um dict
como segundo argumento, que é o contexto que será usado para renderizar o template, cujo arquivo deve estar dentro do diretório templates
.
O renderizador de templates, por default, é o SimpleTemplate que já vem com o Bottle:
Mas você pode usar outro renderizador, bastando sobrescrever o método render
do server. Segue o link para o tal:
Adicionando autenticação
Caso queira requisitar algum tipo de autenticação, você deverá usar o sistema de hooks
do Bottle. Veja um exemplo de autenticação via token:
#!env python3
import json
import bottle
from lazywf import TheLaziestWebFrameworkEVER
class Lazy(TheLaziestWebFrameworkEVER):
def __init__(self, *args, **kwargs):
# Inicialize o server:
super().__init__(*args, **kwargs)
# Depois adicione o hook de autenticação:
self.app.add_hook(‘before_request’, self.check_authentication)
def check_authentication(self):
# Espera-se receber um cabeçalho do tipo:
# Authorization: token TEST
# No qual `TEST` é o token de acesso. auth_value = bottle.request.headers.get(‘authorization’, None)
if auth_value is not None:
_, token = auth_value.split(‘ ‘)
if token == ‘TEST’:
return
error_body = {
‘error_message’: ‘Forbidden’,
‘status_code’: 403,
}
raise bottle.HTTPResponse(status=403, body=json.dumps(error_body))
def create_routes(self):
self.add_route(‘/’, ‘GET’, self.index)
def index(self):
return self.render(‘index.html’)
Lazy().run()
Resumo
Com esse artigo você já tem o caminho das pedras. Em geral, se quiser implementar alguma outra funcionalidade, como servir arquivos estáticos ou algo assim, recomendo primeiro ler o código do lazywf
(é bem curtinho) e depois estudar o Bottle
.
A ideia, novamente, é que você consiga levantar uma API rapidamente para executar algum serviço simples, quando simplesmente não há tempo de se configurar algum framework mais complexo, ou quando você simplesmente quer validar alguma ideia.
Contribuições são sempre bem-vindas. Hoje o projeto precisa de testes automatizados (favor usar pytest
). “Plugins” também são bem-vindos: eles não precisam de um “sistema de plugins”: você pode simplesmente escrever “mixins” a serem herdados pela “classe servidor” (vide o server.py
novamente).
Dê lá sua estrelinha na página do projeto: