web-dev-qa-db-fra.com

HTTPS POST demande Python

Je souhaite faire une demande de publication sur un site HTTPS qui devrait répondre avec un fichier .csv. J'ai ce code Python:

url = 'https://www.site.com/servlet/datadownload'
values = {
  'val1' : '123',
  'val2' : 'abc',
  'val3' : '1b3',
}

data = urllib.urlencode(values)
req = urllib2.Request(url,data)
response = urllib2.urlopen(req)
myfile = open('file.csv', 'wb')
shutil.copyfileobj(response.fp, myfile)
myfile.close()

Mais je reçois l'erreur:

BadStatusLine: ''    (in httplib.py)

J'ai essayé la demande de publication avec Chrome Extension: Advanced REST client (capture d'écran) et cela fonctionne bien.

Quel pourrait être le problème et comment pourrais-je le résoudre? (Est-ce que c'est dû au HTTPS?)


EDIT, code refactored:

try:
    #conn = httplib.HTTPSConnection(Host="www.site.com", port=443)

=> Donne une erreur BadStatusLine: ''

    conn = httplib.HTTPConnection("www.site.com");
    params  = urllib.urlencode({'val1':'123','val2':'abc','val3':'1b3'})
    conn.request("POST", "/nps/servlet/exportdatadownload", params)
    content = conn.getresponse()
    print content.reason, content.status
    print content.read()
    conn.close()
except:
    import sys
    print sys.exc_info()[:2]

Sortie:

Found 302

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>302 Found</TITLE>
</HEAD><BODY>
<H1>Found</H1>
The document has moved <A HREF="https://www.site.com/nps/servlet/exportdatadownload">here</A>.<P>
<HR>
<ADDRESS>Oracle-Application-Server-10g/10.1.3.5.0 Oracle-HTTP-Server Server at mp-www1.mrco.be Port 7778</ADDRESS>
</BODY></HTML>

Qu'est-ce que je fais mal?

8
francisMi

La BadStatusLine: '' (in httplib.py) indique qu'il pourrait se passer autre chose ici. Cela peut se produire lorsque le serveur n'envoie aucune réponse et ferme simplement la connexion.

Comme vous avez mentionné que vous utilisez une connexion SSL, cela pourrait être particulièrement intéressant à déboguer (avec curl -v URL si vous le souhaitez). Si vous découvrez que curl -2 URL (qui force l'utilisation de SSLv2) semble fonctionner, alors que curl -3 URL (SSLv3) ne fonctionne pas, vous voudrez peut-être jeter un coup d'œil au problème # 13636 et éventuellement # 11220 sur le python bugtracker. Selon votre version de Python et un serveur Web éventuellement mal configuré, cela peut être à l'origine d'un problème: les valeurs par défaut de SSL ont été modifiées dans la version 2.7.3.

3
Cedric VB

Y a-t-il une raison pour laquelle vous devez utiliser urllib? Requests est plus simple, meilleur à presque tous les égards, et élimine une partie de la cruauté qui rend urllib difficile à travailler.

Par exemple, je retravaillerais votre exemple en quelque chose comme:

import requests
resp = requests.post(url, data=values, allow_redirects=True)

À ce stade, la réponse du serveur est disponible dans resp.text et vous pouvez en faire ce que vous souhaitez. Si les demandes ne sont pas en mesure de POST correctement (car vous avez besoin d'un certificat SSL personnalisé, par exemple), un message d'erreur Nice vous en avertit.

Même si vous ne pouvez pas faire cela dans votre environnement de production, faites-le dans un shell local pour voir quels messages d'erreur vous recevez de requests et utilisez-les pour déboguer urllib.

11
Dan
   conn = httplib.HTTPSConnection(Host='www.site.com', port=443, cert_file=_certfile)
   params  = urllib.urlencode({'cmd': 'token', 'device_id_st': 'AAAA-BBBB-CCCC',
                                'token_id_st':'DDDD-EEEE_FFFF', 'product_id':'Unit Test',
                                'product_ver':"1.6.3"})
    conn.request("POST", "servlet/datadownload", params)
    content = conn.getresponse().read()
    #print response.status, response.reason
    conn.close()
1
bioffe

Le serveur peut ne pas aimer les en-têtes manquants, en particulier l'agent utilisateur et le type de contenu. L'image Chrome montre ce qui est utilisé pour cela. Peut-être essayez-vous d'ajouter les en-têtes:

import httplib, urllib

Host = 'www.site.com'
url = '/servlet/datadownload'

values = {
  'val1' : '123',
  'val2' : 'abc',
  'val3' : '1b3',
}

headers = {
    'User-Agent': 'python',
    'Content-Type': 'application/x-www-form-urlencoded',
}

values = urllib.urlencode(values)

conn = httplib.HTTPSConnection(Host)
conn.request("POST", url, values, headers)
response = conn.getresponse()

data = response.read()

print 'Response: ', response.status, response.reason
print 'Data:'
print data

Il s'agit d'un code non testé et vous pouvez expérimenter en ajoutant d'autres valeurs d'en-tête correspondant à votre capture d'écran. J'espère que ça aide.

0
Fiver