web-dev-qa-db-fra.com

POST demande avec Multipart/Form-Data. Le type de contenu n'est pas correct

Nous essayons d'écrire un script avec python (à l'aide de python-request a.t.m.) pour envoyer une demande POST à un site où le contenu doit être MultipartFormData. Lorsque nous faisons cette demande POST manuellement (en remplissant le formulaire sur le site et après), à l'aide derowShark, ceci est apparu (version courte):

Content-Type: multipart/form-data;
Content-Disposition: form-data; name="name"
Data (8 Bytes)
    John Doe

Lorsque nous essayons d'utiliser la bibliothèque python-request pour obtenir le même résultat, ceci est envoyé:

Content-Type: application/x-pandoplugin
Content-Disposition: form-data; name="name"; filename="name"\r\n
Media type: application/x-pandoplugin (12 Bytes)
    //and then in this piece is what we posted://
    John Doe

Ce qui est étrange, c’est que le «type général» du paquet est effectivement multipart/form-data, mais l’élément individuel envoyé (clé = 'nom', valeur = 'John Doe') a le type application/x-pandoplugin (un application sur mon pc je suppose).

C'est le code utilisé:

response = s.post('http://url.com', files={'name': 'John Doe'})

Existe-t-il un moyen de spécifier le type de contenu des éléments individuels au lieu d'utiliser l'argument d'en-tête (qui modifie uniquement le type du paquet 'entier')?

Nous pensons que le serveur ne répond pas correctement car il ne comprend pas le type de contenu que nous envoyons.

Petite mise à jour: Je pense que les différentes parties du contenu en plusieurs parties sont maintenant identiques à celles envoyées si je fais le POST dans le navigateur, ce qui est bien. Le serveur ne fait toujours pas les modifications que je lui envoie avec le script. La seule chose qui reste différente est l'ordre des différentes parties. 

Par exemple, voici ce que mon navigateur envoie: 

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part:  (text/plain)
    Content-Disposition: form-data; name="file"; filename="ex.txt"\r\n
    Content-Type: text/plain\r\n\r\n
    Line-based text data: text/plain
        lore ipsum blabbla

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="seq"\r\n\r\n
    Data (2 bytes)

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="name"\r\n\r\n
    Data (2 bytes)

Et voici ce que le script (utilisant python-request) envoie:

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="name"\r\n\r\n
    Data (2 bytes)

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part:  (text/plain)
    Content-Disposition: form-data; name="file"; filename="ex.txt"\r\n
    Content-Type: text/plain\r\n\r\n
    Line-based text data: text/plain
        lore ipsum blabbla

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="seq"\r\n\r\n
    Data (2 bytes)

Pourrait-il être possible que le serveur compte sur l'ordre des pièces? Selon Formulaire d'envoi en plusieurs parties: L'ordre est-il garanti? , c'est apparemment? Et dans l’affirmative, est-il possible de forcer explicitement un ordre à l’aide de la bibliothèque de requêtes?…. Et d’empirer les choses dans ce cas: il existe un mélange de fichier et de valeurs textuelles.

Donc, forcer une commande semble plutôt difficile. Voici comment je le fais actuellement:

s.post('http://www.url.com', files=files,data = form_values)

EDIT2: J'ai modifié le plug-in de requête pour m'assurer que l'ordre des pièces est identique à celui de la requête d'origine. Cela ne résout pas le problème, alors je suppose qu'il n'existe pas de solution simple à mon problème. Je vais envoyer un mail aux développeurs du site et j'espère qu'ils pourront m'aider!

8
HaS

votre code semble correct.

requests.post('http://url.com', files={'name': 'John Doe'})

... et devrait envoyer un message 'multipart/form-data'.

et en effet, je reçois quelque chose comme ceci:

Accept-Encoding: gzip, deflate, compress
Connection: close
Accept: */*
Content-Length: 188
Content-Type: multipart/form-data; boundary=032a1ab685934650abbe059cb45d6ff3
User-Agent: python-requests/1.2.3 CPython/2.7.4 Linux/3.8.0-27-generic

--032a1ab685934650abbe059cb45d6ff3
Content-Disposition: form-data; name="name"; filename="name"
Content-Type: application/octet-stream

John Doe
--032a1ab685934650abbe059cb45d6ff3--

J'ai non idée pourquoi vous obtiendriez cet en-tête bizarre Content-Type:

Content-Type: application/x-pandoplugin

Je commencerais par supprimer complètement Pando Web Plugin de votre machine, puis réessayer votre code de requêtes python. (ou essayez d'une autre machine)

8
Corey Goldberg

A partir d'aujourd'hui vous pouvez faire:

response = s.post('http://url.com', files={'name': (filename, contents, content_type)})
1
pguardiario

Python utilise un fichier de configuration système pour "deviner" le type mime d'un fichier. Si ces plugins enregistrent votre extension de fichier avec leur type mime personnalisé, vous finirez par l'insérer.

L'approche la plus sûre consiste à créer votre propre estimation du type mime qui convient au serveur que vous envoyez, et à n'utiliser que le type natif python pour rechercher des extensions auxquelles vous n'avez pas pensé.

Comment exactement vous spécifiez le type de contenu manuellement avec python-request, je ne le sais pas, mais je suppose que cela devrait être possible.

0
Dobes Vandermeer