【问题标题】:Sending a HTTP POST request from Python (trying to convert from PHP)从 Python 发送 HTTP POST 请求(尝试从 PHP 转换)
【发布时间】:2013-08-07 03:09:09
【问题描述】:

我正在尝试将此代码 sn-p 从 PHP 转换为 Python(编程新手),但我发现这样做有困难:

我要转换的 PHP 如下:

$fp = fsockopen($whmcsurl, 80, $errno, $errstr, 5);
if ($fp) {
$querystring = "";
foreach ($postfields AS $k=>$v) {
$querystring .= "$k=".urlencode($v)."&";
}
$header="POST ".$whmcsurl."modules/servers/licensing/verify.php HTTP/1.0\r\n";
$header.="Host: ".$whmcsurl."\r\n";
$header.="Content-type: application/x-www-form-urlencoded\r\n";
$header.="Content-length: ".@strlen($querystring)."\r\n";
$header.="Connection: close\r\n\r\n";
$header.=$querystring;
$data="";
@stream_set_timeout($fp, 20);
@fputs($fp, $header);
$status = @socket_get_status($fp);
while (!@feof($fp)&&$status) {
$data .= @fgets($fp, 1024);
$status = @socket_get_status($fp);
}
@fclose ($fp);
}

我写的对应的Python代码如下:

fp = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
                fp.connect(("my ip", 80))
                if (fp):
                        querystring = ""
                        #print postfields
                        for key in postfields:
                                querystring = querystring+key+"="+urllib.quote(str(postfields[key]))+"&"
                header = "POST "+whmcsurl+"modules/servers/licensing/verify.php HTTP/1.0\r\n"
                header+="Content-type: application/x-www-form-urlencoded\r\n"
                header+="Content-length: "+str(len(querystring))+"\r\n"
                header+="Connection: close\r\n\r\n"
                #header+=querystring
                data=""
                request = urllib2.Request(whmcsurl,querystring,header)
                response = urllib2.urlopen(request)
                data = response.read()

在这里,我遇到以下错误:

request = urllib2.Request(whmcsurl,querystring,header)
  File "/usr/lib64/python2.6/urllib2.py", line 200, in __init__
    for key, value in headers.items():
AttributeError: 'str' object has no attribute 'items'

所以我猜 Python 需要一个字典作为标题。但是 PHP 将其作为字符串发送。

我可以知道如何解决这个问题吗?

提前致谢

【问题讨论】:

    标签: php python http-headers porting


    【解决方案1】:

    你把事情复杂化了,距离很远。 Python 会为您处理大部分工作。不需要自己打开socket,也不需要构建headers和HTTP开启行。

    使用urllib.requesturllib.parse 模块为您完成工作:

    from urllib.parse import urlopen
    from urllib.request import urlopen
    
    params = urlencode(postfields)
    url = whmcsurl + 'modules/servers/licensing/verify.php'
    response = urlopen(url, params)
    data = response.read()
    

    urlopen() 接受第二个参数,POST 请求中要发送的数据;该库负责计算正文的长度,并设置适当的标题。最重要的是,它使用另一个库 httplib 来处理套接字连接并生成有效的标头和 HTTP 请求行。

    POST 正文使用urllib.parse.urlencode() 编码,它还负责为您正确引用。

    您可能还想查看external requests library,它提供了一个更易于使用的 API:

    import requests
    
    response = requests.post(whmcsurl + 'modules/servers/licensing/verify.php', params=params)
    data = response.content  # or response.text for decoded content, or response.json(), etc.
    

    【讨论】:

    • 那么,在这种情况下,我不需要为表头写代码吗?是params = urlencode(postfields)处理的吗
    • 标头完全由urlopen() 处理。因为您发送了一个正文(第二个参数),所以发送了一个 POST,并且设置了内容类型和内容长度标头。 Host 标头始终设置。
    【解决方案2】:

    你的标题应该是这样的

    headers = { "Content-type" : "application/x-www-form-urlencoded" };
    

    【讨论】:

    • 这里还有很多错误。 POST ... HTTP/1.0 行不是标题,例如在任何情况下都不需要构造。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 2021-01-09
    • 1970-01-01
    • 2016-11-19
    • 1970-01-01
    • 2017-08-22
    • 1970-01-01
    相关资源
    最近更新 更多