[Python] mod_python ed il giusto handler
Andrea Giammarchi
andrea a 3site.it
Mer 16 Ago 2006 18:30:23 CEST
Ma porca trota (scusa, intanto grazie) .. è tutto il pomeriggio che
sbatto la testa con questo mod_python ed ora viene fuori questo
framework favoloso ?
vabbeh ... proverò a continuare per la mia strada (poi un giorno
spiegherò anche il perchè o dove vorrei arrivare) con mod_python
Le conclusioni sono state le seguenti:
- publisher, come handler (credo lo stesso di django o simile), non è
dei più performanti
- psp pare sia tra i più performanti dopo la configurazione a singolo
file (anche se gestisce un embed stile Ruby on Rails o PHP, quindi non
so quanto sia veramente performante ... sicuramente più degli altri
appena citati)
In generale ho notato che la semplicità del php con le cose più banali
($_GET, $_POST, $_FILE) non esiste con nessun handler (ma le super
globali, o almeno la loro netta distinzione, le trovo estremamente utili
...).
Zope da quanto ho visto può andare anche sotto Apache e mod_python, Zope
si prende solo qualche variabile del server per partire e niente più.
Zope l'ho imitato per la scrematura di variabili ad eccezione del path
che l'ho aggiunto.
Mi sono anche scervellato per riuscire a fare una classe per delle super
globali PHP-STYLE molto fake, questo è quanto ne è venuto fuori:
### Andrea Giammarchi
# PHPRequestVars alpha 1
import mod_python
class PHPRequestVars:
def getPHPFakeEnviroment(self):
return {'SERVER':self.__SERVER, 'GET':self.__GET,
'POST':self.__POST, 'FILES':self.__FILES}
def __init__(self, HTTPRequest):
self.__SERVER = {}
self.__GET = {}
self.__POST = {}
self.__FILES = {}
HTTPRequest.add_common_vars()
for k,v in HTTPRequest.subprocess_env.iteritems():
if k.startswith('HTTP_') or k.startswith('PATH_') or
k.startswith('SERVER_') or k.startswith('REQUEST_') or k in
['CONNECTION_TYPE','REMOTE_ADDR','QUERY_STRING','CONTENT_LENGTH','CONTENT_TYPE','SCRIPT_FILENAME']:
self.__SERVER[k] = v
if HTTPRequest.headers_in.has_key('authorization'):
self.__SERVER['HTTP_AUTHORIZATION'] =
HTTPRequest.headers_in['authorization']
self.__SERVER['GATEWAY_INTERFACE'] = 'Python/mod_python.publisher'
self.__SERVER['SCRIPT_NAME'] = ''
if self.__SERVER.has_key('REQUEST_URI'):
self.__SERVER['PATH_TRANSLATED'] =
self.__SERVER['PATH_INFO'] = self.__SERVER['REQUEST_URI'].split('?')[0]
if self.__SERVER.has_key('HTTP_CONNECTION'):
self.__SERVER['CONNECTION_TYPE'] =
self.__SERVER['HTTP_CONNECTION']
if self.__SERVER.has_key('QUERY_STRING') and
len(self.__SERVER['QUERY_STRING']) > 0:
self.__initGet(self.__SERVER['QUERY_STRING'].split('&'))
if self.__SERVER.has_key('REQUEST_METHOD') and
self.__SERVER['REQUEST_METHOD'] == 'POST':
self.__initPostAndFiles(HTTPRequest)
def __initGet(self, queryString):
j = len(queryString)
tmp = []
for i in range(0, j):
tmp = queryString[i].split('=')
if len(tmp) == 2:
self.__GET[tmp[0]] = tmp[1]
else:
self.__GET[tmp[0]] = ''
def __initPostAndFiles(self, HTTPRequest):
tmplist = mod_python.util.FieldStorage(HTTPRequest).list
j = len(tmplist)
for i in range(0, j):
if tmplist[i].file.__class__.__name__ !=
'_TemporaryFileWrapper':
if not self.__GET.has_key(tmplist[i].name):
self.__POST[tmplist[i].name] = tmplist[i].value
elif self.__GET[tmplist[i].name] != tmplist[i].value:
self.__POST[tmplist[i].name] = tmplist[i].value
else:
cname = tmplist[i].value
self.__FILES[tmplist[i].name] = {
'name':tmplist[i].filename,
'type':tmplist[i].type,
'tmp_name':tmplist[i].file.__dict__['name'],
'size':len(cname),
'data':cname,
'error':0
}
e questa è la pagina index.psp che sto usando per fare i tests:
<%
from PHPRequestVars import *
def index(HTTPRequest):
buffer = []
phpFakeEnv = PHPRequestVars(HTTPRequest).getPHPFakeEnviroment()
_SERVER = phpFakeEnv['SERVER']
_GET = phpFakeEnv['GET']
_POST = phpFakeEnv['POST']
_FILES = phpFakeEnv['FILES']
buffer.append('<pre>')
for k in _POST:
buffer.append('_POST: %s %s<br />' % (k, _POST[k]))
buffer.append('</pre>')
buffer.append('<pre>')
for k in _GET:
buffer.append('_GET: %s %s<br />' % (k, _GET[k]))
buffer.append('</pre>')
buffer.append('<pre>')
for k in _FILES:
buffer.append('_FILES: %s %s<br />' % (k,
_FILES[k]['name']))
buffer.append('</pre>')
buffer.append('<hr /><pre>')
for k in _SERVER:
buffer.append('_SERVER: %s %s<br />' % (k, _SERVER[k]))
buffer.append('</pre>')
HTTPRequest.content_type = "text/html"
HTTPRequest.send_http_header()
HTTPRequest.write("".join(buffer))
index(req)
%>
Ora, funziona tutto alla perfezione (almeno dai tests che ho fatto io)
ma ho un enorme dubbio sulla variabile _FILE, in particolare in questo
pezzo:
cname = tmplist[i].value
self.__FILES[tmplist[i].name] = {
'name':tmplist[i].filename,
'type':tmplist[i].type,
'tmp_name':tmplist[i].file.__dict__['name'],
'size':len(cname),
'data':cname,
'error':0
}
il dubbio nasce dal fatto che mod_python si comporta in modo diverso da
mod_php e da quanto ho letto cname = tmplist[i].value può mandare in
tilt il web-server perchè carica in memoria tutto il file come stringa
binaria non appena richiamato.
Non ho trovato il modo di prendere la size del file inviato se non
sfruttando la len del binario ed a quel punto ho optato per l'aggiunta
di un campo data contenente tale stringa.
Ovviamente se i files sono molto grandi il server va in crisi .... avete
consigli sul come gestire il tutto o chiudere il file inviato al fine di
poter leggere la size e non quella attesa, ovvero 0L ??? (os.stat(..)[6]
già provato)
Grazie ancora, se sono uscito dal tema apro un'altra email ?
Saluti,
Andrea Giammarchi
P.S. ogni altro consiglio sul codice postato è ben accetto
Carlo C8E Miron ha scritto:
>> - ce ne sono altri ??? ... qual'è il più usato ?
>
> Django, <http://djangoproject.com/>
Maggiori informazioni sulla lista
Python