Crear y analizar solicitudes HTTP multiparte en Python

Estoy tratando de escribir un código de Python que pueda crear solicitudes http de mime multiparte en el cliente y luego interpretarlo adecuadamente en el servidor. Creo que tuve éxito en el extremo del cliente con esto:

from email.mime.multipart import MIMEMultipart, MIMEBase
import httplib
h1 = httplib.HTTPConnection('localhost:8080')
msg = MIMEMultipart()
fp = open('myfile.zip', 'rb')
base = MIMEBase("application", "octet-stream")
base.set_payload(fp.read())
msg.attach(base)
h1.request("POST", "http://localhost:8080/server", msg.as_string())

El único problema con esto es que la biblioteca de correo electrónico también incluye los encabezados Content-Type y MIME-Version, y no estoy seguro de cómo se relacionarán con los encabezados HTTP incluidos en httplib:

Content-Type: multipart/mixed; boundary="===============2050792481=="
MIME-Version: 1.0

--===============2050792481==
Content-Type: application/octet-stream
MIME-Version: 1.0

Esta puede ser la razón por la que cuando mi solicitud web.py recibe esta solicitud, recibo un mensaje de error. El controlador POST web.py:

class MultipartServer:
    def POST(self, collection):
        print web.input()

Lanza este error:

Traceback (most recent call last):
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/application.py", line 242, in process
    return self.handle()
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/application.py", line 233, in handle
    return self._delegate(fn, self.fvars, args)
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/application.py", line 415, in _delegate
    return handle_class(cls)
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/application.py", line 390, in handle_class
    return tocall(*args)
  File "/home/richard/Development/server/webservice.py", line 31, in POST
    print web.input()
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/webapi.py", line 279, in input
    return storify(out, *requireds, **defaults)
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/utils.py", line 150, in storify
    value = getvalue(value)
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/utils.py", line 139, in getvalue
    return unicodify(x)
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/utils.py", line 130, in unicodify
    if _unicode and isinstance(s, str): return safeunicode(s)
  File "/usr/local/lib/python2.6/dist-packages/web.py-0.34-py2.6.egg/web/utils.py", line 326, in safeunicode
    return obj.decode(encoding)
  File "/usr/lib/python2.6/encodings/utf_8.py", line 16, in decode
    return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 137-138: invalid data

Mi línea de código está representada por la línea de error aproximadamente a la mitad:

  File "/home/richard/Development/server/webservice.py", line 31, in POST
    print web.input()

Está llegando, pero no estoy seguro de a dónde ir desde aquí. ¿Es este un problema con mi código de cliente o una limitación de web.py (tal vez simplemente no puede admitir solicitudes de varias partes)? Cualquier sugerencia o sugerencia de bibliotecas de códigos alternativos sería gratamente recibida.

EDITAR

El error anterior se debe a que los datos no se codifican automáticamente en base64. Agregando

encoders.encode_base64(base)

Se deshace de este error, y ahora el problema está claro. La solicitud HTTP no se interpreta correctamente en el servidor, presumiblemente porque la biblioteca de correo electrónico incluye lo que deberían ser los encabezados HTTP en el cuerpo:

<Storage {'Content-Type: multipart/mixed': u'', 
          ' boundary': u'"===============1342637378=="\n'
          'MIME-Version: 1.0\n\n--===============1342637378==\n'
          'Content-Type: application/octet-stream\n'
          'MIME-Version: 1.0\n' 
          'Content-Transfer-Encoding: base64\n'
          '\n0fINCs PBk1jAAAAAAAAA.... etc

Entonces algo no está bien allí.

Gracias

Ricardo

Respuestas a la pregunta(3)

Su respuesta a la pregunta