How to rewrite this POST curl script in python? - php

I'm going to rewrite this POST request in python:
<?php
// Set these variables
$networkid = ""; // In your HasOffers system at Support -> API
$apikey = ""; // In your HasOffers system at Support -> API
$offerid = "0"; // Specify an offer ID to add the creative to
$creativetype = "image banner"; // Types: file, image banner, flash banner, email creative, offer thumbnail, text ad, html ad, hidden
$filename = "banner_728x90.gif"; // File name; no spaces, and file must be in same directory as this script
$display = $filename; // Or change this to the "display name" for this creative
// Don't change anything below here
$creativetype = urlencode($creativetype);
$display = urlencode($display);
$fields[$filename] = "#{$filename}";
$url = "http://api.hasoffers.com/v3/OfferFile.json?Method=create&NetworkToken={$apikey}&NetworkId={$networkid}&data[offer_id]={$offerid}&data[type]={$creativetype}&data[display]={$display}&return_object=1";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
$resp = curl_exec($ch);
curl_close($ch);
print_r(json_decode($resp, true)); // Final output; remove or change this if you want
?>
As I know, in pycurl the CURLOPT_POSTFIELDS attribute is absent. What can I use instead?
Thank you!

there are many python libraries that can be used:
http.client
https://docs.python.org/3.1/library/http.client.html
requests
https://pypi.python.org/pypi/requests/
the commands are pretty straightforwards:
using http.client:
import http.client
conn = http.client.HTTPConnection("www.python.org")
conn.request("HEAD","/index.html")
res = conn.getresponse()
print(res.status, res.reason)
200 OK
or requests:
import requests
r = requests.get('https://github.com/timeline.json')
print r.json
Using HTTP client, a simple POST request may be done as follows:
connect = http.client.HTTPSConnection("base_url")
connect.request('POST', '/rest/api/'+ you_can_add_variables+ '/users?userEmail=' + another_variable, headers=headers)
Using requests:
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
headers = {'content-type': 'application/json'}
r = requests.post(url, data=json.dumps(payload), headers=headers)
the documentation provided above should not prove difficult to understand

Related

Multipart Form CURL request in PHP uploading image

I am trying to use a PHP CURL request to upload data to Pass Slot to change an image, and I am continually getting errors.
This is the CURL request needed from their developer section on their website
POST https://api.passslot.com/v1/passes/pass.example.id1/27f145d2-5713-4a8d-af64-b269f95ade3b/images/thumbnail/normal
and this is the data that needs to be sent in its requested format
------------------------------330184f75e21
Content-Disposition: form-data; name="image"; filename="icon.png"
Content-Type: application/octet-stream
.PNG
imagedata
This is the code I am using currently, as I am not familiar with what is required on Multipart Form requests on API
$passId = "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx";
$pass_generate_url = "pass.xxxxxxxxxxxx";
$url1 = 'https://api.passslot.com/v1/passes/'.$pass_generate_url.'/'.$passId.'/images/strip/normal';
$logo_file_location = "image.png";
$logo_file_location1 = "http://xxxxxxx.com/uploads/";
$data1 = array('image' => '#uploads/'.$logo_file_location,'application/octet-string',$logo_file_location1,'some_other_field' => 'abc',);
$auth1 = array( 'Authorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=',
'Content-Type: text/plain');
$ch1 = curl_init($url1);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch1, CURLOPT_POST, 1);
curl_setopt($ch1, CURLOPT_POSTFIELDS, $data1);
curl_setopt($ch1, CURLOPT_HEADER, 0);
curl_setopt($ch1, CURLOPT_HTTPHEADER, $auth1);
$response1 = curl_exec($ch1);
$ch1 = curl_init($url1);
When I run the code, this is the response from the CURL I get
{"message":"Validation Failed","errors":[{"field":"image","reasons":["Required"]}]}
Is there something I need to add to make the code work please?
Yes, I think you can build your own curl including to use say PHP CURLFile (sending the Multipart delimiter boundary and then the graphic data, etc) But you may choose to use an API (Say PassSlot PHP SDK)
https://github.com/passslot/passslot-php-sdk
General usage
require 'passslot-php-sdk/src/PassSlot.php';
$engine = PassSlot::start('<YOUR APP KEY>');
$pass = $engine->createPassFromTemplate(<Template ID>);
$engine->redirectToPass($pass);
For PNG file, it is like:
<?php
require_once('../src/PassSlot.php');
$appKey ='<YOUR APP KEY>';
$passTemplateId = 123456;
$outputPass = FALSE;
$values = array(
'Name' => 'John',
'Level' => 'Platinum',
'Balance' => 20.50
);
$images = array(
'thumbnail' => dirname(__FILE__) . '/thumbnail.png'
);
try {
$engine = PassSlot::start($appKey);
$pass = $engine->createPassFromTemplate($passTemplateId, $values, $images);
if($outputPass) {
$passData = $engine->downloadPass($pass);
$engine->outputPass($passData);
} else {
$engine->redirectToPass($pass);
}
} catch (PassSlotApiException $e) {
echo "Something went wrong:\n";
echo $e;
}
For further reference, please visit this
https://github.com/passslot/passslot-php-sdk/blob/master/examples/example.php
You may also view the source of the API to get inspired:
https://github.com/passslot/passslot-php-sdk/blob/master/src/PassSlot.php
Additional remark:
In case there is certificate expiry warning/error when running the SDK, please download the latest cacert.pem from https://curl.se/docs/caextract.html and replace the one in the SDK

Upload large files to Dropbox via HTTP API

I am currently implementing an upload mechanism for files on my webserver into my Dropbox app directory.
As stated on the API docs, there is the /upload endpoint (https://www.dropbox.com/developers/documentation/http/documentation#files-upload) which accepts files up to 150MB in size. However I‘m dealing with images and videos with a potential size of up to 2GB.
Therefore I need to use the upload_session endpoints. There is an endpoint to start the session (https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start), to append data and to finish the session.
What currently is unclear to me is how to exactly use these endpoints. Do I have to split my file on my server into 150MB chunks (how would I do that with a video file?) and then upload the first chunk with /start, the next chunks with /append and the last one with /finish? Or can I just specify the file and the API somehow (??) does the splitting for me? Obviously not, but I somehow can‘t get my head around on how I should calculate, split and store the chunks on my webserver and not lose the session inbetween...
Any advice or further leading links are greatly appreciated. Thank you!
As Greg mentioned in the comments, you decide how to manage the "chunks" of the files. In addition to his .NET example, Dropbox has a good upload session implementation in the JavaScript upload example of the Dropbox API v2 JavaScript SDK.
At a high-level, you're splitting up the file into smaller sizes (aka "chunks") and passing those to the upload_session mechanism in a specific order. The upload mechanism has a few parts that need to be used in the following order:
Call /files/upload_session/start. Use the resulting session_id as a parameter in the following methods so Dropbox knows which session you're interacting with.
Incrementally pass each "chunk" of the file to /files/upload_session/append_v2. A couple things to be aware of:
The first call will return a cursor, which is used to iterate over the file's chunks in a specific order. It gets passed as a parameter in each consecutive call to this method (with the cursor being updated on every response).
The final call must include the property "close": true, which closes the session so it can be uploaded.
Pass the final cursor (and commit info) to /files/upload_session/finish. If you see the new file metadata in the response, then you did it!!
If you're uploading many files instead of large ones, then the /files/upload_session/finish_batch and /files/upload_session/finish_batch/check are the way to go.
I know this is an old post, but here is a fully functional solution for your problem. Maybe anyone else finds it usefull. :)
<?php
$backup_folder = glob('/var/www/test_folder/*.{sql,gz,rar,zip}', GLOB_BRACE); // Accepted file types (sql,gz,rar,zip)
$token = '<ACCESS TOKEN>'; // Dropbox Access Token;
$append_url = 'https://content.dropboxapi.com/2/files/upload_session/append_v2';
$start_url = 'https://content.dropboxapi.com/2/files/upload_session/start';
$finish_url = 'https://content.dropboxapi.com/2/files/upload_session/finish';
if (!empty($backup_folder)) {
foreach ($backup_folder as $single_folder_file) {
$file_name= basename($single_folder_file); // File name
$destination_folder = 'destination_folder'; // Dropbox destination folder
$info_array = array();
$info_array["close"] = false;
$headers = array(
'Authorization: Bearer ' . $token,
'Content-Type: application/octet-stream',
'Dropbox-API-Arg: '.json_encode($info_array)
);
$chunk_size = 50000000; // 50mb
$fp = fopen($single_folder_file, 'rb');
$fileSize = filesize($single_folder_file); // File size
$tosend = $fileSize;
$first = $tosend > $chunk_size ? $chunk_size : $tosend;
$ch = curl_init($start_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, fread($fp, $first));
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($ch);
$tosend -= $first;
$resp = explode('"',$response);
$sesion = $resp[3];
$position = $first;
$info_array["cursor"] = array();
$info_array["cursor"]["session_id"] = $sesion;
while ($tosend > $chunk_size)
{
$info_array["cursor"]["offset"] = $position;
$headers[2] = 'Dropbox-API-Arg: '.json_encode($info_array);
curl_setopt($ch, CURLOPT_URL, $append_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, fread($fp, $chunk_size));
curl_exec($ch);
$tosend -= $chunk_size;
$position += $chunk_size;
}
unset($info_array["close"]);
$info_array["cursor"]["offset"] = $position;
$info_array["commit"] = array();
$info_array["commit"]["path"] = '/'. $destination_folder . '/' . $file_name;
$info_array["commit"]["mode"] = array();
$info_array["commit"]["mode"][".tag"] = "overwrite";
$info_array["commit"]["autorename"] = true;
$info_array["commit"]["mute"] = false;
$info_array["commit"]["strict_conflict"] = false;
$headers[2] = 'Dropbox-API-Arg: '. json_encode($info_array);
curl_setopt($ch, CURLOPT_URL, $finish_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, $tosend > 0 ? fread($fp, $tosend) : null);
curl_exec($ch);
curl_close($ch);
fclose($fp);
unlink($single_folder_file); // Remove files from server folder
}
}

Convert PHP Curl To Python

I've been trying to translate some PHP code to Python 3 but can't quite get it to work. In PHP I have the following:
$request = "https://api.example.com/token";
$developerKey = "Basic VVVfdFdfsjkUIHDfdsjYTpMX3JQSDNJKSFQUkxCM0p0WWFpRklh";
$data = array('grant_type'=>'password',
'username'=>'name',
'password'=>'pass',
'scope'=>'2346323');
$cjconn = curl_init($request);
curl_setopt($cjconn, CURLOPT_POST, TRUE);
curl_setopt($cjconn, CURLOPT_HTTPHEADER, array('Authorization: '.$developerKey));
curl_setopt($cjconn, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($cjconn, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($cjconn, CURLOPT_POSTFIELDS,http_build_query($data));
$result = curl_exec($cjconn);
curl_close($cjconn);
$tokens = json_decode($result,true);
$accesstoken = $tokens['access_token'];
echo $accesstoken."\n";
I tried converting it to the following in Python:
import pycurl, json
url = 'https://api.example.com/token'
data = json.dumps({"grant_type":"password",
"username":"name",
"password":"pass",
"scope":"2346323"})
key = 'Basic VVVfdFdfsjkUIHDfdsjYTpMX3JQSDNJKSFQUkxCM0p0WWFpRklh'
c = pycurl.Curl()
c.setopt(pycurl.URL,url)
c.setopt(pycurl.HTTPHEADER,['Authorization: {}'.format(key)])
c.setopt(pycurl.POST,1)
c.setopt(pycurl.POSTFIELDS,data)
c.perform()
But I get the following error:
<faultstring>String index out of range: -1</faultstring>
How can I correct this, or is there a more pythonic solution?
If anyone is interested in the solution, I came up with the following which worked:
def getToken(self):
"""Retrieves the token from provider"""
#The data to be passed to retrieve the token
tokenData = {'grant_type':'password',
'username':TOKENUSERNAME,
'password':TOKENPASSWORD,
'scope':TOKENSCOPE}
#The header parameters
header_params = {'Authorization':KEY}
#Make the request for the token
r = requests.post(TOKENURL,data=tokenData,headers=header_params)
#Check the status code
if r.status_code not in [200,203]:
self.log.logentry("There was an error retrieving the data from Linkshare: {}:{}".format(r.status_code,r.text))
sys.exit()
#Extract the data from the response
data = r.json()
#Parse the access token
token = {'token':data['access_token'],
'type':data['bearer']}
return token

Golang vs PHP https calls with headers different results

I am trying to implement Vault of Satoshi's API in Google App Engine Go. Their reference API is in PHP:
<?php
$serverURL = 'https://api.vaultofsatoshi.com';
$apiKey = 'ENTER_YOUR_API_KEY_HERE';
$apiSecret = 'ENTER_YOUR_API_SECRET_HERE';
function usecTime() {
list($usec, $sec) = explode(' ', microtime());
$usec = substr($usec, 2, 6);
return intval($sec.$usec);
}
$url = 'https://api.vaultofsatoshi.com';
$endpoint = '/info/currency';
$url = $serverURL . $endpoint;
$parameters= array();
$parameters['nonce'] = usecTime();
$data = http_build_query($parameters);
$httpHeaders = array(
'Api-Key: ' . $apiKey,
'Api-Sign:' . base64_encode(hash_hmac('sha512', $endpoint . chr(0) . $data, $apiSecret)),
);
// Initialize the PHP curl agent
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT, "something specific to me");
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FAILONERROR, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$output = curl_exec($ch);
curl_close($ch);
echo $output;
?>
My Go code looks like this:
func GenerateSignatureFromValues(secretKey string, endpoint string, values url.Values) string {
query:=[]byte(values.Encode())
toEncode:=[]byte(endpoint)
toEncode = append(toEncode, 0x00)
toEncode = append(toEncode, query...)
key:=[]byte(secretKey)
hmacHash:=hmac.New(sha512.New, key)
hmacHash.Write(toEncode)
answer := hmacHash.Sum(nil)
return base64.StdEncoding.EncodeToString(([]byte(strings.ToLower(hex.EncodeToString(answer)))))
}
func Call(c appengine.Context) map[string]interface{} {
serverURL:="https://api.vaultofsatoshi.com"
apiKey:="ENTER_YOUR_API_KEY_HERE"
apiSecret:="ENTER_YOUR_API_SECRET_HERE"
endpoint:="/info/order_detail"
tr := urlfetch.Transport{Context: c}
values := url.Values{}
values.Set("nonce", strconv.FormatInt(time.Now().UnixNano()/1000, 10))
signature:=GenerateSignatureFromValues(apiSecret, endpoint, values)
req, _:=http.NewRequest("POST", serverURL+endpoint, nil)
req.Form=values
req.Header.Set("Api-Key", apiKey)
req.Header.Set("Api-Sign", signature)
resp, err:=tr.RoundTrip(req)
if err != nil {
c.Errorf("API post error: %s", err)
return nil
}
defer resp.Body.Close()
body, _:= ioutil.ReadAll(resp.Body)
result := make(map[string]interface{})
json.Unmarshal(body, &result)
return result
}
Both of those pieces of code generate the same signature for the same input. However, when I run the PHP code (with the proper Key and Secret), the server responds with a proper response, but while I run the Go code, the server responds with "Invalid signature". This error indicates that the HTTP request generated by Go must be somehow malformed - either HTTP Header's values are wrong (if the header values are completely missing a different error appears), or the way the POST fields are encoded is wrong for some reason.
Can anyone help me find some reason why those two pieces of code generate different HTTP requests and how can I make Go generate requests like the PHP code?
See the documentation for Request.Form:
// Form contains the parsed form data, including both the URL
// field's query parameters and the POST or PUT form data.
// This field is only available after ParseForm is called.
// The HTTP client ignores Form and uses Body instead.
Form url.Values
Specifically "HTTP client ignores Form and uses Body instead."
With this line:
req, _:= http.NewRequest("POST", serverURL+endpoint, nil)
You should use this instead of nil:
bytes.NewBufferString(values.Encode())
Also keep in mind that the order of map is not guaranteed. url.Values is map[string][]string. So you should be using Encode() once and use the same result in the body and signature. There is a chance that by using Encode() twice the order could be different. This is an important difference between Go and PHP.
You should also make a habit of handling error instead of ignoring it.

equal of php in asp.net

what is the equivalent code in asp.net language???
<?php
$ch = curl_init("http://irnafiarco.com/queue");
$request["queue"] = file_get_contents("/path_to_my_xml_file/my_xml_file.xml");
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$response = curl_exec($ch);
curl_close ($ch);
echo $response;
?>
in http://irnafiarco.com/queue a Listener that get requst xml file and saver xml file.
Using WebRequest, this will be the basic code
var req = WebRequest.Create(#"http://irnafiarco.com/queue"))
// prepare the request
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
// push the file contents into request body
var data = "queue=" + System.IO.File.OpenText(filePath).ReadToEnd();
var bytes = System.Text.Encoding.Ascii.GetBytes(data );
request.ContentLength = bytes.Length;
var rs = req.GetRequestStream();
rs.Write(bytes, 0, bytes.Length);
rs.Close ();
// get the response
var resp = req.GetResponse();
var sr = new System.IO.StreamReader(resp.GetResponseStream());
var result = sr.ReadToEnd();
Disclaimer: untested code
EDIT:
Added the post parameter name ("queue") which I have missed in first draft. Also added content-length for the request. This code should get you started. The basic idea is you need to simulate exact post request generated by PHP code. Use tool such as Fiddler/ Firebug on FF to inspect & compare request/response from PHP and .NET code.
Further, I suspect that the PHP code may generating request with content type as multipart/form-data. However, I believe that server should also able to support the post body with application/x-www-form-urlencoded (because we have only one parameter in body) but in case it doesn't work and you must generate POST body as multipart/form-data then it will be little more involved. See this SO question where accepted answer has given the sample code for the same : Upload files with HTTPWebrequest (multipart/form-data)
Take a look at WebRequest, WebProxy classes which are inline with what you're after...
WebRequest request = WebRequest.Create(url);
request.Proxy = new WebProxy("http://blahblahblah", true)
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
// handle response here
Also, see here, and here, though may not be relevant for your implementation
Examples of using these to fetch XML abound, i.e.:
System.Net.HttpWebRequest webRequest = (HttpWebRequest)System.Net.WebRequest.Create("yourURL.xml");
webRequest.Credentials = System.Net.CredentialCache.DefaultCredentials;
webRequest.Accept = "text/xml";
System.Net.HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse();
System.IO.Stream responseStream = webResponse.GetResponseStream();
System.Xml.XmlTextReader reader = new XmlTextReader(responseStream);
//Do something meaningful with the reader here
reader.Close();
webResponse.Close();

Categories