Fix für httplib.HTTPResponse.read

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
hinnerk
User
Beiträge: 2
Registriert: Samstag 8. November 2008, 15:58

In httplib.HTTPResponse.read steckt ein bekannter Bug, der bei Requests mit "transfer-encoding: chunked" und ohne Body (z.B. "HEAD") in ein deadlock führt (siehe http://bugs.python.org/issue6312). Nun habe vorhin einen schnellen Fix geschrieben: Einen monkey patch, der die Methode global ersetzt.

Gibt es einen besseren Weg, Fehler in mitgelieferten Bibliotheken los zu werden?

Code: Alles auswählen

import hashlib
import inspect
import httplib

__bad_read = "801726b8e58a929be9ce667cf727c7f9"
if hashlib.md5(inspect.getsource(httplib.HTTPResponse.read)).hexdigest() == __bad_read:
    # mostly copied from [...]/python2.6/httplib.py HTTPResponse.read
    def __good_read(self, amt=None):
        if self.fp is None:
            return ''
        if self.chunked:
            if amt is None: # These lines are the only difference to original
                return ""   # read(). Without them a chunked HEAD would block.
            return self._read_chunked(amt)
        if amt is None:
            if self.length is None:
                s = self.fp.read()
            else:
                s = self._safe_read(self.length)
                self.length = 0
            self.close()        # we read everything
            return s
        if self.length is not None:
            if amt > self.length:
                amt = self.length
        s = self.fp.read(amt)
        if self.length is not None:
            self.length -= len(s)
            if not self.length:
                self.close()
        return s
    # monkeys were here!
    httplib.HTTPResponse.read = __good_read
Zuletzt geändert von hinnerk am Donnerstag 21. Januar 2010, 17:43, insgesamt 1-mal geändert.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

Sauberer wäre es, eine Subklasse zu benutzen oder wenigstens die Original-Methode weiterhin für alle Fälle zu verwenden, die nicht durch den Patch abgedeckt werden, um Änderungen an der Original-Methode nicht für alle Zeit zu ignorieren.

Code: Alles auswählen

class MyHTTPResponse(HTTPResponse):
    def read(self, amt=None):
        if self.chunked and amt is None:
            return ""
       return super(MyHTTPResponse, self).read(atm=atm)
oder

Code: Alles auswählen

HTTPResponse.read_original = HTTPResponse.read
def __read_patch(self, atm=None):
    if self.chunked and amt is None:
        return ""
    return self.read_original(atm=atm)
HTTPResponse.read = __read_patch
Bottle: Micro Web Framework + Development Blog
Antworten