HTTPS POST запрос Python

Я хочу сделать запрос post на HTTPS-сайт ,который должен отвечать.CSV-файл. У меня есть этот код:

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()

но получаю ошибку:

BadStatusLine: ''    (in httplib.py)

Я пробовал запрос post с расширением Chrome: Advanced rest client (видео) и это прекрасно работает.

что может быть проблемой и как я могу ее решить? (это из-за HTTPS?)


изменить, перестроить код:

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

=> дает 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]

выход:

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>

что я делаю не так?

4 ответов


на BadStatusLine: '' (in httplib.py) выдает, что здесь может быть что-то еще. Это может произойти, когда сервер вообще не отправляет ответ и просто закрывает соединение.

как вы упомянули, что вы используете SSL-соединение, это может быть особенно интересно для отладки (с curl -v URL Если вы хотите). Если вы узнаете, что curl -2 URL (что заставляет использовать SSLv2), кажется, работает, в то время как curl -3 URL (SSLv3), не, вы можете взглянуть на проблему #13636 и возможно!--9-->#11220 на python bugtracker. В зависимости от вашей версии Python и, возможно, неправильно настроенного веб-сервера, это может вызвать проблему: значения по умолчанию SSL изменились в v2.7.3.


есть причина, по которой вы должны использовать urllib? запросы проще, лучше почти во всех отношениях, и абстрагирует некоторые из cruft, что делает urllib трудно работать.

в качестве примера я бы переделал вам пример как-то вроде:

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

на данный момент, ответ от сервера доступно в resp.text, и вы можете делать с ним все, что захотите. Если запросы не удалось опубликовать должным образом (потому что вам нужен пользовательский сертификат SSL, для пример), он должен дать вам хорошее сообщение об ошибке, которое скажет вам, почему.

даже если вы не можете сделать это в своей рабочей среде, сделайте это в локальной оболочке, чтобы узнать, какие сообщения об ошибках вы получаете от requests, и используйте это для отладки urllib.


   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()

серверу могут не понравиться отсутствующие заголовки, особенно user-agent и content-type. Изображение Chrome показывает, что используется для них. Возможно, попробуйте добавить заголовки:

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

это непроверенный код, и вы можете экспериментировать, добавляя другие значения заголовка в соответствии с вашим скриншотом. Надеюсь, это поможет.