HTTPS POST 请求 Python

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14385173/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 11:15:57  来源:igfitidea点击:

HTTPS POST request Python

pythonposthttpsurllib2urllib

提问by francisMi

I want to make a post request to a HTTPS-site that should respond with a .csv file. I have this Python code:

我想向一个 HTTPS 站点发出一个 post 请求,该请求应该以 .csv 文件进行响应。我有这个 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()

But 'm getting the error:

但是我收到错误:

BadStatusLine: ''    (in httplib.py)

I've tried the post request with the Chrome Extension: Advanced REST client (screenshot)and that works fine.

我已经尝试过使用 Chrome 扩展程序发布请求:高级 REST 客户端(屏幕截图)并且工作正常。

What could be the problem and how could I solve it? (is it becasue of the HTTPS?)

可能是什么问题,我该如何解决?(是因为HTTPS吗?)



EDIT, refactored code:

编辑,重构代码:

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

=> Gives an BadStatusLine: ''error

=> 给出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]

Output:

输出:

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>

What am I doing wrong?

我究竟做错了什么?

采纳答案by Cedric VB

The BadStatusLine: '' (in httplib.py)gives away that there might be something else going on here. This may happen when the server sends no reply back at all, and just closes the connection.

BadStatusLine: '' (in httplib.py)表明这里可能还有其他事情发生。这可能发生在服务器根本不发送任何回复,而只是关闭连接时。

As you mentioned that you're using an SSL connection, this might be particularly interesting to debug (with curl -v URLif you want). If you find out that curl -2 URL(which forces the use of SSLv2) seems to work, while curl -3 URL(SSLv3), doesn't, you may want to take a look at issue #13636and possibly #11220on the python bugtracker. Depending on your Python version & a possibly misconfigured webserver, this might be causing a problem: the SSL defaults have changed in v2.7.3.

正如您提到的,您正在使用 SSL 连接,这对调试可能特别有趣(curl -v URL如果您愿意的话)。如果您发现curl -2 URL(强制使用 SSLv2)似乎有效,而curl -3 URL(SSLv3) 无效,您可能需要查看python bugtracker上的 issue #13636#11220。根据您的 Python 版本和可能配置错误的网络服务器,这可能会导致问题:v2.7.3 中的 SSL 默认值已更改。

回答by bioffe

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

回答by Dan

Is there a reason you've got to use urllib? Requestsis simpler, better in almost every way, and abstracts away some of the cruft that makes urllibhard to work with.

你有理由使用urllib吗?请求更简单,几乎在所有方面都更好,并且抽象了一些难以使用的杂物urllib

As an example, I'd rework you example as something like:

举个例子,我会把你的例子改写为:

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

At this point, the response from the server is available in resp.text, and you can do what you'd like with it. If requests wasn't able to POST properly (because you need a custom SSL certificate, for example), it should give you a nice error message that tells you why.

此时,来自服务器的响应在 中可用resp.text,您可以对它进行任何操作。如果请求无法正确 POST(例如,因为您需要自定义 SSL 证书),它应该会给您一个很好的错误消息,告诉您原因。

Even if you can't do this in your production environment, do this in a local shell to see what error messages you get from requests, and use that to debug urllib.

即使您无法在生产环境中执行此操作,也可以在本地 shell 中执行此操作以查看从 中获得的错误消息requests,并使用它来调试urllib.

回答by Fiver

The server may not like the missing headers, particularly user-agent and content-type. The Chrome image shows what is used for these. Maybe try adding the headers:

服务器可能不喜欢缺少的标头,尤其是 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

This is untested code, and you may want to experiment by adding other header values to match your screenshot. Hope it helps.

这是未经测试的代码,您可能希望通过添加其他标题值来匹配您的屏幕截图来进行试验。希望能帮助到你。