Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending a HTTP POST request from Python (trying to convert from PHP)

I am trying to convert this code snippet from PHP to Python (programming newbie) and am finding difficulty in doing so:

The PHP that I am trying to convert is as follows:

$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);
}

It corresponding Python code that I wrote is as follows:

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

Here, I am faced with the following error:

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'

So I am guessing that Python is expecting a dictionary for the header. But the PHP sends it as a string.

May I know how to solve this issue?

Thanks in advance

like image 678
rahuL Avatar asked Jan 12 '23 17:01

rahuL


1 Answers

You are overcomplicating things, by quite some distance. Python takes care of most of this for you. There is no need to open a socket yourself, nor do you need to build headers and the HTTP opening line.

Use the urllib.request and urllib.parse modules to do the work for you:

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() takes a second parameter, the data to be sent in a POST request; the library takes care of calculating the length of the body, and sets the appropriate headers. Most of all, under the hood it uses another library, httplib, to take care of the socket connection and producing valid headers and a HTTP request line.

The POST body is encoded using urllib.parse.urlencode(), which also takes care of proper quoting for you.

You may also want to look into the external requests library, which provides an easier-to-use API still:

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.
like image 127
Martijn Pieters Avatar answered Jan 16 '23 02:01

Martijn Pieters