[Patches] httplib.py timeout

Aahz aahz@searchbutton.com
Fri, 11 Feb 2000 15:58:26 -0800


This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.

------_=_NextPart_000_01BF74EB.E343222C
Content-Type: text/plain;
	charset="iso-8859-1"

This patch allows the user of httplib.py to specify a timeout in
milliseconds.  If a timeout is not specified, a default of sixty seconds is
assumed.  The user may specify no timeout by passing a timeout of zero.
This patch is intended to be especially useful to urllib.py; there was
discussion of this patch in comp.lang.python at the end of December, with
general agreement that this patch is appropriate.

I'm submitting this patch against CVS, but the patch has only been tested
against 1.5.2.  Let me know if you have any problems.

Disclaimer (approved by my boss at Searchbutton.com):

I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.



------_=_NextPart_000_01BF74EB.E343222C
Content-Type: application/octet-stream;
	name="httplib.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="httplib.diff"

*** httplib.py.CVS	Fri Feb 11 15:41:58 2000=0A=
--- httplib.py	Fri Feb 11 15:51:39 2000=0A=
***************=0A=
*** 41,46 ****=0A=
--- 41,47 ----=0A=
  HTTP_VERSION =3D 'HTTP/1.0'=0A=
  HTTP_PORT =3D 80=0A=
  HTTPS_PORT =3D 443=0A=
+ SOCKET_TIMEOUT =3D 60 * 1000   # Sixty seconds=0A=
  =0A=
  class FakeSocket:=0A=
      def __init__(self, sock, ssl):=0A=
***************=0A=
*** 69,87 ****=0A=
  class HTTP:=0A=
      """This class manages a connection to an HTTP server."""=0A=
  =0A=
!     def __init__(self, host =3D '', port =3D 0, **x509):=0A=
          """Initialize a new instance.=0A=
  =0A=
          If specified, `host' is the name of the remote host to =
which=0A=
          to connect.  If specified, `port' specifies the port to =
which=0A=
!         to connect.  By default, httplib.HTTP_PORT is used.=0A=
  =0A=
          """=0A=
          self.key_file =3D x509.get('key_file')=0A=
          self.cert_file =3D x509.get('cert_file')=0A=
          self.debuglevel =3D 0=0A=
          self.file =3D None=0A=
!         if host: self.connect(host, port)=0A=
  =0A=
      def set_debuglevel(self, debuglevel):=0A=
          """Set the debug output level.=0A=
--- 70,91 ----=0A=
  class HTTP:=0A=
      """This class manages a connection to an HTTP server."""=0A=
  =0A=
!     def __init__(self, host =3D '', port =3D 0, timeout =3D None, =
**x509):=0A=
          """Initialize a new instance.=0A=
  =0A=
          If specified, `host' is the name of the remote host to =
which=0A=
          to connect.  If specified, `port' specifies the port to =
which=0A=
!         to connect.  By default, httplib.HTTP_PORT is used.  If =
specified,=0A=
!         timeout is the socket timeout in milliseconds.  By =
default,=0A=
!         httplib.SOCKET_TIMEOUT is used.  If timeout =3D=3D 0, then no =
timeout=0A=
!         is used.=0A=
  =0A=
          """=0A=
          self.key_file =3D x509.get('key_file')=0A=
          self.cert_file =3D x509.get('cert_file')=0A=
          self.debuglevel =3D 0=0A=
          self.file =3D None=0A=
!         if host: self.connect(host, port, timeout)=0A=
  =0A=
      def set_debuglevel(self, debuglevel):=0A=
          """Set the debug output level.=0A=
***************=0A=
*** 92,99 ****=0A=
          """=0A=
          self.debuglevel =3D debuglevel=0A=
  =0A=
!     def connect(self, host, port =3D 0):=0A=
!         """Connect to a host on a given port.=0A=
  =0A=
          Note:  This method is automatically invoked by __init__,=0A=
          if a host is specified during instantiation.=0A=
--- 96,104 ----=0A=
          """=0A=
          self.debuglevel =3D debuglevel=0A=
  =0A=
!     def connect(self, host, port =3D 0, timeout =3D None):=0A=
!         """Connect to a host on a given port with timeout in =
milliseconds.=0A=
!         No timeout if timeout =3D=3D 0.=0A=
  =0A=
          Note:  This method is automatically invoked by __init__,=0A=
          if a host is specified during instantiation.=0A=
***************=0A=
*** 108,113 ****=0A=
--- 113,131 ----=0A=
                      raise socket.error, "nonnumeric port"=0A=
          if not port: port =3D HTTP_PORT=0A=
          self.sock =3D socket.socket(socket.AF_INET, =
socket.SOCK_STREAM)=0A=
+         # Use try/except to catch platforms where socket options =
unavailable=0A=
+         if timeout is None:=0A=
+             try:=0A=
+                 self.sock.setsockopt(socket.SOL_SOCKET, =0A=
+                     socket.SO_RCVTIMEO, SOCKET_TIMEOUT)=0A=
+             except:=0A=
+                 pass=0A=
+         elif timeout > 0:=0A=
+             try:=0A=
+                 self.sock.setsockopt(socket.SOL_SOCKET, =0A=
+                     socket.SO_RCVTIMEO, timeout)=0A=
+             except:=0A=
+                 pass=0A=
          if self.debuglevel > 0: print 'connect:', (host, port)=0A=
          self.sock.connect(host, port)=0A=
  =0A=
***************=0A=
*** 192,199 ****=0A=
      class HTTPS(HTTP):=0A=
          """This class allows communication via SSL."""=0A=
  =0A=
!         def connect(self, host, port =3D 0):=0A=
!             """Connect to a host on a given port.=0A=
  =0A=
              Note:  This method is automatically invoked by =
__init__,=0A=
              if a host is specified during instantiation.=0A=
--- 210,218 ----=0A=
      class HTTPS(HTTP):=0A=
          """This class allows communication via SSL."""=0A=
  =0A=
!         def connect(self, host, port =3D 0, timeout =3D None):=0A=
!             """Connect to a host on a given port with timeout in =
milliseconds.=0A=
!             No timeout if timeout =3D=3D 0.=0A=
  =0A=
              Note:  This method is automatically invoked by =
__init__,=0A=
              if a host is specified during instantiation.=0A=
***************=0A=
*** 208,213 ****=0A=
--- 227,246 ----=0A=
                          raise socket.error, "nonnumeric port"=0A=
              if not port: port =3D HTTPS_PORT=0A=
              sock =3D socket.socket(socket.AF_INET, =
socket.SOCK_STREAM)=0A=
+             # Use try/except to catch platforms where socket options =
=0A=
+             # unavailable=0A=
+             if timeout is None:=0A=
+                 try:=0A=
+                     self.sock.setsockopt(socket.SOL_SOCKET, =0A=
+                         socket.SO_RCVTIMEO, SOCKET_TIMEOUT)=0A=
+                 except:=0A=
+                     pass=0A=
+             elif timeout > 0:=0A=
+                 try:=0A=
+                     self.sock.setsockopt(socket.SOL_SOCKET, =0A=
+                         socket.SO_RCVTIMEO, timeout)=0A=
+                 except:=0A=
+                     pass=0A=
              if self.debuglevel > 0: print 'connect:', (host, port)=0A=
              sock.connect(host, port)=0A=
              ssl =3D socket.ssl(sock, self.key_file, =
self.cert_file)=0A=

------_=_NextPart_000_01BF74EB.E343222C--