Merge branch 'urlloader_curl' into all
This commit is contained in:
@@ -11,6 +11,14 @@ import js.Browser;
|
||||
import js.Lib;
|
||||
#end
|
||||
|
||||
#if lime_curl
|
||||
import lime.net.curl.CURL;
|
||||
import lime.net.curl.CURLEasy;
|
||||
import lime.net.curl.CURLCode;
|
||||
import lime.net.curl.CURLInfo;
|
||||
import lime.net.curl.CURLOption;
|
||||
#end
|
||||
|
||||
|
||||
class URLLoader {
|
||||
|
||||
@@ -26,13 +34,22 @@ class URLLoader {
|
||||
public var onProgress = new Event<URLLoader->Int->Int->Void> ();
|
||||
public var onSecurityError = new Event<URLLoader->String->Void> ();
|
||||
|
||||
#if lime_curl
|
||||
private var __curl:CURL;
|
||||
private var __data:String;
|
||||
#end
|
||||
|
||||
public function new (request:URLRequest = null) {
|
||||
|
||||
bytesLoaded = 0;
|
||||
bytesTotal = 0;
|
||||
dataFormat = URLLoaderDataFormat.TEXT;
|
||||
|
||||
|
||||
#if lime_curl
|
||||
__data = "";
|
||||
__curl = CURLEasy.init();
|
||||
#end
|
||||
|
||||
if (request != null) {
|
||||
|
||||
load (request);
|
||||
@@ -44,7 +61,9 @@ class URLLoader {
|
||||
|
||||
public function close ():Void {
|
||||
|
||||
|
||||
#if lime_curl
|
||||
CURLEasy.cleanup(__curl);
|
||||
#end
|
||||
|
||||
}
|
||||
|
||||
@@ -60,6 +79,8 @@ class URLLoader {
|
||||
|
||||
#if js
|
||||
requestUrl (request.url, request.method, request.data, request.formatRequestHeaders ());
|
||||
#elseif lime_curl
|
||||
requestUrl (request.url, request.method, request.data, request.formatRequestHeaders ());
|
||||
#end
|
||||
|
||||
}
|
||||
@@ -227,6 +248,144 @@ class URLLoader {
|
||||
};
|
||||
|
||||
}
|
||||
#elseif lime_curl
|
||||
|
||||
private function prepareData(data:Dynamic):ByteArray {
|
||||
|
||||
var uri:ByteArray = new ByteArray();
|
||||
if (Std.is (data, ByteArray)) {
|
||||
|
||||
var data:ByteArray = cast data;
|
||||
uri = data;
|
||||
|
||||
} else if (Std.is (data, URLVariables)) {
|
||||
|
||||
var data:URLVariables = cast data;
|
||||
var tmp:String = "";
|
||||
for (p in Reflect.fields (data)) {
|
||||
|
||||
if (tmp.length != 0) tmp += "&";
|
||||
tmp += StringTools.urlEncode (p) + "=" + StringTools.urlEncode (Reflect.field (data, p));
|
||||
|
||||
}
|
||||
|
||||
uri.writeUTFBytes(tmp);
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
if (data != null) {
|
||||
|
||||
uri.writeUTFBytes(Std.string(data));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return uri;
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
switch(method) {
|
||||
case HEAD:
|
||||
CURLEasy.setopt(__curl, NOBODY, true);
|
||||
case GET:
|
||||
CURLEasy.setopt(__curl, HTTPGET, true);
|
||||
case POST:
|
||||
CURLEasy.setopt(__curl, POST, true);
|
||||
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, INFILESIZE, uri.length);
|
||||
case _:
|
||||
CURLEasy.setopt(__curl, CUSTOMREQUEST, cast method);
|
||||
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}');
|
||||
|
||||
}
|
||||
|
||||
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, "libcurl-agent/1.0");
|
||||
|
||||
var result = CURLEasy.perform(__curl);
|
||||
|
||||
|
||||
var responseCode = CURLEasy.getinfo(__curl, RESPONSE_CODE);
|
||||
|
||||
if (result == CURLCode.OK) {
|
||||
/*
|
||||
switch(dataFormat) {
|
||||
case BINARY: this.data = __data;
|
||||
default: this.data = __data.asString();
|
||||
}
|
||||
*/
|
||||
this.data = __data;
|
||||
onHTTPStatus.dispatch (this, Std.parseInt(responseCode));
|
||||
onComplete.dispatch (this);
|
||||
} else {
|
||||
onIOError.dispatch (this, "Problem with curl: " + result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function writeFunction (output:String, size:Int, nmemb:Int):Int {
|
||||
|
||||
__data += output;
|
||||
return size * nmemb;
|
||||
|
||||
}
|
||||
|
||||
private function headerFunction (output:String, size:Int, nmemb:Int):Int {
|
||||
|
||||
// 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);
|
||||
}
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<set name="OUTPUT_DIR" value="../ndll" unless="OUTPUT_DIR" />
|
||||
<set name="NATIVE_TOOLKIT_PATH" value="lib" unless="NATIVE_TOOLKIT_PATH" />
|
||||
|
||||
<set name="LIBCURL_SSL" value="1" />
|
||||
<set name="NATIVE_TOOLKIT_CURL_SSL" value="1" />
|
||||
|
||||
<files id="lime">
|
||||
|
||||
|
||||
Submodule project/lib/curl updated: 96d4700e32...10e4ec2b11
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user