WSGI
Web Server Gateway Interface
Python
- O que é e por quê?
- Web server, aplicação e middleware
- Conclusão
- + info e referências
PEP 333 v1.0
7 de dezembro de 2003
- Primeira versão
PEP 3333 v1.0.1
26 de setembro de 2010
- Versão atual, compatível com tudo da anterior;
- suporte a Python 3 (principalmente problemas relacionados a unicode)
O que é?
Especificação
Standard Python. Descrito em detalhes nas PEPs abaixo.
web server
ou gateway
aplicação
framework
W
S
G
I
O que é?
Interface
Uma camada que fica entre a applicação e o web server, criando assim um meio comum de comunicação entre ambos.
W
S
G
I
request
response
Por que?
Escolha
uWSGI
Gunicorn
CherryPy
Flask
Django
Falcon
WSGI
Poder escolher entre diferentes web servers e frameworks.
{
'HTTP_HOST': 'localhost',
'PATH_INFO': '/healthcheck',
'REQUEST_METHOD': 'GET',
'SERVER_NAME': 'localhost',
'SERVER_PORT': '80',
'SERVER_PROTOCOL': 'HTTP/1.0',
...
'wsgi.url_scheme': 'http',
'wsgi.version': (1, 0),
...
}Por que?
Portabilidade
O environ WSGI é muito parecido com o environ CGI, e adiciona somente algumas chaves a mais. Assim, facilita a portabilidade de aplicações legadas.
Web Server
WSGI
Middleware
WSGI
Aplicação
WSGI
request
request
response
response
Por que?
Middlewares
Provê uma maneira simples de adicionar middlewares à aplicação...
...e encadeá-los
Web Server
socket
Web Server
bind
listen
accept
socket conectado
import socket
serversocket = socket.socket(...)
...
serversocket.bind(('localhost', 8888))
serversocket.listen(1)
while True:
conn, addr = serversocket.accept()
request = conn.recv(1024)
print request
response = ...
conn.sendall(response)
conn.close()Implementando um web server simples
Web Server
accept
socket conectado
$ telnet localhost 8888
Trying 127.0.0.1 …
Connected to localhost.
GET /healthcheck HTTP/1.1
HTTP/1.1 200 OK
WorkingHTTP request
TCP Connection
Web Server
class WSGIServer(object):
...
def __init__(self, server_address):
# socket
self.headers_set = []
...
def handle_one_request(self):
# parse request, etc
result = self.application(environ, self.start_response)
self.finish_response(result)
# vai pegar o status e headers de self.headers_set, concatenar
# com result (response body), enviar e fechar a conexão
...
def start_response(self, status, response_headers):
server_headers = [...]
self.headers_set = [status, response_headers + server_headers]
...
if __name__ == '__main__':
# importa a app, seta o server_address, instancia WSGIServer e seta app
server.serve_forever() # handle_one_requestImplementação WSGI
Web Server
possíveis melhorias
- Fazer o web server gerenciar mais de um request por vez;
- melhorar aspectos de configuração;
- tunar a performance;
- etc & etc;
- ou usar Gunicorn, uWSGI, ...
Aplicação
Aplicação
def application(environ, start_response):
start_response("200 OK", [('Content-Type', 'text/plain')])
return ["Working"]Uma função ou classe Python chamável ( ! ) que retorna ao web server o status, o response body e response headers
response body
status
response headers
Aplicação
possíveis melhorias
- Criar um gerenciamento de rotas: ao verificar PATH_INFO podemos delegar qual função ou classe manipula determinada url (via regex por exemplo);
- adicionar um sistema de templates para tratar o response body;
- etc & etc;
- ou usar Flask, Django, ...
Middleware
Middleware
Simplificando, o middleware nada mais é do que uma parte do web server que recebe a aplicação e a aplicação em si. Pode realizar alterações tanto no request quanto no response.
class WSGIMiddleware(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
return self.app(environ, start_response)
Middleware
Um middleware mais útil: adiciona ao request um header customizado
class MyHeaderMiddleware(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
def custom_start_response(status, headers):
headers.append(('X-My-Header', "Made by MyHeaderMiddleware"))
return start_response(status, headers)
return self.app(environ, custom_start_response)Conclusão
- É uma interface simples e fácil de implementar. Cria uma forma consistente de um web server repassar dados para uma aplicação e esperar por uma resposta;
- middlewares são uma ótima alternativa para extender a aplicação, mas muitos criticam o uso desenfreado.
+ info
- Algumas outras linguagens também implementaram a especificação como Ruby (Rack), Javascript (JSGI), Perl (PSGI), etc;
- possui poucos elementos para deploy e configuração. O utilitário Python Paste, por exemplo, tenta resolver isso (e um monte de outras coisas);
Algumas referências
- wsgi.org
- python.org/dev/peps/pep-3333
- lucumr.pocoo.org/2007/5/21/getting-started-with-wsgi
WSGI
By Alan
WSGI
Web Server Gateway Interface
- 325