Créer et analyser multipart des requêtes HTTP en Python
Je suis en train d'écrire du code python qui peut créer multipart mime requêtes http dans le client, puis de façon appropriée interpréter ensuite sur le serveur. J'ai, je pense, partiellement réussi sur le client:
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())
Le seul problème avec ceci est que l'e-mail de la bibliothèque comprend également le Type de Contenu et le MIME-Version les en-têtes, et je ne suis pas sûr de savoir comment ils vont être liées à des en-têtes HTTP inclus par httplib:
Content-Type: multipart/mixed; boundary="===============2050792481=="
MIME-Version: 1.0
--===============2050792481==
Content-Type: application/octet-stream
MIME-Version: 1.0
Cela peut être la raison que, lorsque cette demande est reçue par mon web.py l'application, je viens d'obtenir un message d'erreur. L'web.py POSTE de gestionnaire:
class MultipartServer:
def POST(self, collection):
print web.input()
Met cette erreur:
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
Ma ligne de code est représenté par la ligne d'erreur à mi-chemin vers le bas:
File "/home/richard/Development/server/webservice.py", line 31, in POST
print web.input()
C'est en cours, mais je ne sais pas où aller à partir d'ici. Est-ce un problème avec mon code client, ou une limitation de web.py (peut-être qu'il ne peut tout simplement pas soutenir multipart demandes)? Tous conseils ou des suggestions de code alternatif bibliothèques seront reçues avec reconnaissance.
MODIFIER
L'erreur ci-dessus a été causé par les données n'étant pas automatiquement encodées en base64. L'ajout de
encoders.encode_base64(base)
De se débarrasser de cette erreur, et maintenant, le problème est clair. Requête HTTP n'est pas interprété correctement dans le serveur, sans doute parce que l'e-mail de la bibliothèque est notamment ce que devraient être les en-têtes HTTP dans le corps au lieu:
<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
Si quelque chose n'est pas là.
Grâce
Richard
oui. oui, il est.
OriginalL'auteur Richard J | 2010-12-13
Vous devez vous connecter pour publier un commentaire.
J'ai utilisé ce package Sera Holcomb http://pypi.python.org/pypi/MultipartPostHandler/0.1.0 de faire du multi-partie des demandes avec urllib2, il peut vous aider.
OriginalL'auteur justinfay
Après un peu d'exploration, la réponse à cette question est évidente. La réponse courte est que, bien que la Content-Disposition est facultative dans un message codé de Mime, web.py exige pour chaque mime-partie afin d'analyser correctement la requête HTTP.
Contrairement à d'autres commentaires sur cette question, la différence entre HTTP et courrier Électronique est hors de propos, car ils sont tout simplement des mécanismes de transport pour le message Mime et rien de plus. Multipart/related (pas multipart/form-data) les messages sont communs, dans le contenu de l'échange de services web, ce qui est le cas ici. Les extraits de code fournis sont exacts, et qu', et m'a conduit à un peu plus courts, la solution au problème.
C'est pris parfaitement bien par web.py, donc, il est clair que l'e-mail.le mime.multipart est adapté pour la création de messages Mime à être transportés par HTTP, à l'exception de son en-tête de la manipulation.
Mon autre globale du problème est dans l'évolutivité. Ni la solution, ni les autres, proposé ici à l'échelle eh bien, comme ils lire le contenu d'un fichier dans une variable avant de s'emmitoufler dans le message mime. Une meilleure solution serait celle qui pourrait serialise sur la demande que le contenu transmis est transmis via la connexion HTTP. C'est pas urgent pour moi de corriger ça, mais je vais revenir ici avec une solution, si je peux.
base.add_header('Content-Disposition','file',name='package',...)
. 2. Il est préférable de rechercher\n\n
(et aussi\r\n\r\n
, avec, par exemple,re.search('\r?\n\r?\n',...)
) de sorte que vous n'avez pas à se fendre et à se joindre au corps. 3. Lignes d'en-tête peut être plié. 4. Techniquement, le\n
qui termine les en-têtes n'est pas une partie du corps, même si ce n'est pas nocif. 5. Je ne suis pas entièrement sûr que la RFC 5322 et RFC 2316 grammaires sont 100% compatibles (en particulier WRT "caractères" vs octets).OriginalL'auteur Richard J
Il y a un certain nombre de choses de mal avec votre demande. Comme TokenMacGuy suggère, multipart/mixed n'est pas utilisé dans HTTP; utilisation multipart/form-data à la place. En outre, les parties doivent avoir un Contenu en-tête de disposition. Un python fragment à faire qui peut être trouvé dans la Code De Recettes.
Voir la recette. Oubliez sujet de l'email.mime - HTTP n'est pas e-mail.
Salut Martin; pour info je l'ai démontré que la différence entre HTTP et courrier électronique est hors de propos ici - ils sont tout simplement des transports, et mime est la même dans les deux cas. Voir ma réponse alternative. Merci pour les pointeurs. R
C'est faux,
multipart/mixed
est utilisé dans HTTP: docs.couchdb.org/en/latest/replication/...OriginalL'auteur Martin v. Löwis