[Python-de] urllib2.HTTPRedirectHandler und komprimierte Requests

Andreas Pakulat apaku at gmx.de
Don Mai 11 00:14:36 CEST 2006


Hi,

ich hab hier ein verzwicktest "Problem" mit dem Tool reportbug aus
Debian. Das Ding prüft anhand von Website-Anfragen ob ein installiertes
Paket aktuell ist und ob irgendwelche Bugreports dazu existieren bevor
man einen neuen schreiben darf. 

Weiterhin sitze ich hinter einem AFAIK transparenten Proxy (sprich ich
weiss eigentlich nicht das da einer ist) der offensichtlich etwas mehr
tut als nur HTTP Requests und Response "weiterzuleiten" und evtl. zu
cachen.

Folgendes Szenario: reportbug erzeugt einen HTTP Request mit unter
anderem folgenden Header:

'Accept-Encoding' : 'gzip;q=1.0, deflate;q=0.9, identity;q=0.5'

Die Debian-Server beantworten das ganze _immer_ mit einem
nicht-komprimierten Response. Allerdings interessiert das den Proxy
nicht, Anfragen dieser Art kommen komprimiert zurueck. 

Nun zum eigentlichen Problem: Die Antwort ist ein Redirect-Response
(sorry HTTP Code ist mir grad entfallen) und mit folgendem:

        handlers = [proxy_support,
            urllib2.UnknownHandler, HttpWithGzipHandler,
            urllib2.HTTPBasicAuthHandler(pwd_manager),
            urllib2.ProxyBasicAuthHandler(pwd_manager),
            urllib2.HTTPDigestAuthHandler(pwd_manager),
            urllib2.ProxyDigestAuthHandler(pwd_manager),
            urllib2.HTTPDefaultErrorHandler, urllib2.HTTPRedirectHandler,
        ]
        if hasattr(httplib, 'HTTPS'):
            handlers.append(HttpsWithGzipHandler)
        _opener = urllib2.build_opener(*handlers)
         urllib2.install_opener(_opener)
         return _opener.open(req)

wird dann der urllib2.HTTPRedirectHandler "angeschmissen" und sendet
entsprechend einen neuen Request. Dieser neue Request hat aber nun kein
Accept-Encoding mehr gesetzt und demzufolge kommt die Antwort
unkomprimiert daher. 

Meine Frage an euch ist erstmal nur: Ist das Verhalten vom
Redirect-Handler so korrekt, oder sollte er den originalen Request
erneut an die andere URL schicken und somit auch den Accept-Encoding
Header?

Das eigentliche Problem ist dann naemlich der HttpWithGzipHandler und
die Header des Response, der Handler sieht so aus:

class HttpWithGzipHandler (urllib2.HTTPHandler):
    "support gzip encoding"
    def http_open (self, req):
        return decode(urllib2.HTTPHandler.http_open(self, req))

und decode beginnt so:

def decode (page):
    "gunzip or deflate a compressed page"
    encoding = page.info().get("Content-Encoding")
    if encoding in ('gzip', 'x-gzip', 'deflate'):

Die Kodierung des Inhalts wird hier als gzip angegeben, aber in
wirklichkeit ist da reiner Text drin. Ich lasse mir in pythons
GzipFile._read_gzip_header() naemlich die ersten 2 Bytes ausgeben und
das sind nicht die 2 magic-bytes fuer gzip, sondern normaler Text.

Saemtliche Ideen wie ich dem ganzen auf die Schliche komme oder es
"repariere" sind willkommen. Wer den kompletten Source-Code von
reportbug sehen will ziehe sich bitte:

http://ftp.de.debian.org/debian/pool/main/r/reportbug/reportbug_3.20.tar.gz

Die Dateien urlutils.py und checkversions.py (Funktion
get_versions_available) enthalten die wesentlichen Teile. 

Andreas

PS: Nein ich will nicht das ihr das fuer mich debuggt, nur Tipps wie ich
da am besten rangehe... Der Maintainer des Pakets kann das ganze
natuerlich nicht reproduzieren da kein transparenter Proxy im Weg ist..

-- 
Today is the last day of your life so far.