Continue the work with URLLoader and cURL

- Fixed PUT and POST
- Fixes CURLOPT_READFUNCTION
- Added CURLOPT_PROGRESSFUNCTION
This commit is contained in:
MrCdK
2014-08-26 07:46:43 +02:00
parent 0fef12abba
commit bdf8d1f2f1
2 changed files with 96 additions and 26 deletions

View File

@@ -253,7 +253,6 @@ class URLLoader {
private function prepareData(data:Dynamic):ByteArray {
var uri:ByteArray = new ByteArray();
if (Std.is (data, ByteArray)) {
var data:ByteArray = cast data;
@@ -270,14 +269,14 @@ class URLLoader {
}
uri.writeUTF(tmp);
uri.writeUTFBytes(tmp);
} else {
if (data != null) {
uri.writeUTF(Std.string(data));
uri.writeUTFBytes(Std.string(data));
}
@@ -290,8 +289,12 @@ class URLLoader {
private function requestUrl (url:String, method:URLRequestMethod, data:Dynamic, requestHeaders:Array<URLRequestHeader>):Void {
var uri = prepareData(data);
uri.position = 0;
__data = "";
bytesLoaded = 0;
bytesTotal = 0;
CURLEasy.reset(__curl);
CURLEasy.setopt(__curl, URL, url);
@@ -302,16 +305,21 @@ class URLLoader {
CURLEasy.setopt(__curl, HTTPGET, true);
case POST:
CURLEasy.setopt(__curl, POST, true);
CURLEasy.setopt(__curl, READFUNCTION, readFunction.bind(_, _, _, uri));
CURLEasy.setopt(__curl, READFUNCTION, readFunction.bind(_, uri));
CURLEasy.setopt(__curl, POSTFIELDSIZE, uri.length);
CURLEasy.setopt(__curl, INFILESIZE, uri.length);
case PUT:
CURLEasy.setopt(__curl, UPLOAD, true);
CURLEasy.setopt(__curl, READFUNCTION, readFunction.bind(_, _, _, uri));
CURLEasy.setopt(__curl, READFUNCTION, readFunction.bind(_, uri));
CURLEasy.setopt(__curl, INFILESIZE, uri.length);
case _:
CURLEasy.setopt(__curl, CUSTOMREQUEST, cast method);
CURLEasy.setopt(__curl, READFUNCTION, readFunction.bind(_, _, _, uri));
CURLEasy.setopt(__curl, READFUNCTION, readFunction.bind(_, uri));
CURLEasy.setopt(__curl, INFILESIZE, uri.length);
}
var headers:Array<String> = [];
headers.push("Expect: "); // removes the default cURL value
for (requestHeader in requestHeaders) {
headers.push('${requestHeader.name}: ${requestHeader.value}');
@@ -320,11 +328,14 @@ class URLLoader {
CURLEasy.setopt(__curl, HTTPHEADER, headers);
CURLEasy.setopt(__curl, PROGRESSFUNCTION, progressFunction);
CURLEasy.setopt(__curl, WRITEFUNCTION, writeFunction);
CURLEasy.setopt(__curl, HEADERFUNCTION, headerFunction);
CURLEasy.setopt(__curl, SSL_VERIFYPEER, false);
CURLEasy.setopt(__curl, SSL_VERIFYHOST, false);
CURLEasy.setopt(__curl, USERAGENT, "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0");
CURLEasy.setopt(__curl, USERAGENT, "libcurl-agent/1.0");
var result = CURLEasy.perform(__curl);
@@ -339,32 +350,40 @@ class URLLoader {
}
*/
this.data = __data;
onComplete.dispatch (this);
onHTTPStatus.dispatch (this, Std.parseInt(responseCode));
onComplete.dispatch (this);
} else {
onIOError.dispatch (this, "Problem with curl: " + result);
}
}
private function writeFunction (output:String, chunks:Int, length:Int):Int {
private function writeFunction (output:String, size:Int, nmemb:Int):Int {
__data += output;
return chunks * length;
return size * nmemb;
}
private function readFunction (output:String, chunks:Int, length:Int, input:ByteArray):Int {
private function headerFunction (output:String, size:Int, nmemb:Int):Int {
var chunk = chunks * length;
var inputTotal = input.length - input.position;
if(inputTotal < chunk) {
output += input.readUTFBytes(inputTotal);
return 0;
// TODO
return size * nmemb;
}
private function progressFunction (dltotal:Float, dlnow:Float, uptotal:Float, upnow:Float):Int {
if(upnow>bytesLoaded || dlnow>bytesTotal) {
if(upnow > bytesLoaded) bytesLoaded = Std.int(upnow);
if(dlnow > bytesTotal) bytesTotal = Std.int(dlnow);
onProgress.dispatch(this, bytesLoaded, bytesTotal);
}
output += input.readUTFBytes(chunk);
return chunk;
return 0;
}
private function readFunction(max:Int, input:ByteArray):String {
return input == null ? "" : input.readUTFBytes(Std.int(Math.min(max, input.length - input.position)));
}
#end

View File

@@ -1,5 +1,6 @@
#include <curl/curl.h>
#include <hx/CFFI.h>
#include <string.h>
namespace lime {
@@ -157,7 +158,7 @@ namespace lime {
}
static size_t rw_callback (void *ptr, size_t size, size_t nmemb, void *userp) {
static size_t write_callback (void *ptr, size_t size, size_t nmemb, void *userp) {
AutoGCRoot* callback = (AutoGCRoot*)userp;
@@ -171,6 +172,37 @@ namespace lime {
return val_int (val_call3 (callback->get (), str, alloc_int (size), alloc_int (nmemb)));
}
static size_t read_callback (void *buffer, size_t size, size_t nmemb, void *userp) {
AutoGCRoot* callback = (AutoGCRoot*)userp;
size_t bytes = size * nmemb;
const char *input = val_string (val_call1 (callback->get (), alloc_int (bytes)));
size_t length = strlen(input);
if(length <= bytes) bytes = length;
memcpy(buffer, input, bytes);
return bytes;
}
static size_t progress_callback (void *userp, double dltotal, double dlnow, double ultotal, double ulnow) {
AutoGCRoot* callback = (AutoGCRoot*)userp;
value vals[] = {
alloc_float(dltotal),
alloc_float(dlnow),
alloc_float(ultotal),
alloc_float(ulnow),
};
return val_int (val_callN (callback->get (), vals, 4));
}
value lime_curl_easy_setopt (value handle, value option, value parameter) {
@@ -366,12 +398,8 @@ namespace lime {
case CURLOPT_OPENSOCKETDATA:
case CURLOPT_CLOSESOCKETFUNCTION:
case CURLOPT_CLOSESOCKETDATA:
case CURLOPT_PROGRESSFUNCTION:
case CURLOPT_PROGRESSDATA:
case CURLOPT_XFERINFOFUNCTION:
//case CURLOPT_XFERINFODATA:
case CURLOPT_HEADERFUNCTION:
case CURLOPT_HEADERDATA:
case CURLOPT_DEBUGFUNCTION:
case CURLOPT_DEBUGDATA:
case CURLOPT_SSL_CTX_FUNCTION:
@@ -406,13 +434,36 @@ namespace lime {
//case CURLOPT_READDATA:
//case CURLOPT_WRITEDATA:
//case CURLOPT_HEADERDATA:
//case CURLOPT_PROGRESSDATA:
case CURLOPT_READFUNCTION:
{
AutoGCRoot* callback = new AutoGCRoot (parameter);
code = curl_easy_setopt (curl, type, read_callback);
curl_easy_setopt (curl, CURLOPT_READDATA, callback);
break;
}
case CURLOPT_WRITEFUNCTION:
{
AutoGCRoot* callback = new AutoGCRoot (parameter);
code = curl_easy_setopt (curl, type, rw_callback);
curl_easy_setopt (curl, type == CURLOPT_READFUNCTION ? CURLOPT_READDATA : CURLOPT_WRITEDATA, callback);
code = curl_easy_setopt (curl, type, write_callback);
curl_easy_setopt (curl, CURLOPT_WRITEDATA, callback);
break;
}
case CURLOPT_HEADERFUNCTION:
{
AutoGCRoot* callback = new AutoGCRoot (parameter);
code = curl_easy_setopt (curl, type, write_callback);
curl_easy_setopt (curl, CURLOPT_HEADERDATA, callback);
break;
}
case CURLOPT_PROGRESSFUNCTION:
{
AutoGCRoot* callback = new AutoGCRoot (parameter);
code = curl_easy_setopt (curl, type, progress_callback);
curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, callback);
curl_easy_setopt (curl, CURLOPT_NOPROGRESS, false);
break;
}