[ https://issues.apache.org/jira/browse/THRIFT-3876?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15380097#comment-15380097 ]
ASF GitHub Bot commented on THRIFT-3876: ---------------------------------------- Github user Jens-G commented on a diff in the pull request: https://github.com/apache/thrift/pull/1045#discussion_r71039726 --- Diff: lib/haxe/src/org/apache/thrift/transport/THttpClient.hx --- @@ -94,10 +114,241 @@ class THttpClient extends TTransport { } }; + #if js + request_.onBinaryData = function(data : Bytes) { + responseBuffer_ = new BytesInput(data); + if( callback != null) { + callback(null); + } + }; + + request_.setBinaryPostData(buffer.getBytes()); + #else request_.setPostData(buffer.getBytes().toString()); + #end request_.request(true/*POST*/); } - } - \ No newline at end of file +#if js +/*supports sending/receiving binary/json data (browser, nodejs) + implemented atop https://github.com/HaxeFoundation/haxe/blob/development/std/haxe/Http.hx + */ +class JsHttp extends Http { + var binaryPostData : Bytes; + + public function setBinaryPostData( data : Bytes ):Http { + binaryPostData = data; + return this; + } + + public dynamic function onBinaryData( data : Bytes ) { + } + + #if !nodejs + public override function request( ?post : Bool ) : Void { + var me = this; + me.responseData = null; + var r = req = js.Browser.createXMLHttpRequest(); + var onreadystatechange = function(_) { + if( r.readyState != 4 ) + return; + var s = try r.status catch( e : Dynamic ) null; + if ( s != null && untyped __js__('"undefined" !== typeof window') ) { + // If the request is local and we have data: assume a success (jQuery approach): + var protocol = js.Browser.location.protocol.toLowerCase(); + var rlocalProtocol = ~/^(?:about|app|app-storage|.+-extension|file|res|widget):$/; + var isLocal = rlocalProtocol.match( protocol ); + if ( isLocal ) { + s = r.responseText != null ? 200 : 404; + } + } + if( s == untyped __js__("undefined") ) + s = null; + if( s != null ) + me.onStatus(s); + if( s != null && s >= 200 && s < 400 ) { + me.req = null; + var len = r.responseText.length; + var bytes = new BytesOutput(); + bytes.prepare(len); + for(i in 0 ... len) { + var byte = (r.responseText.charCodeAt(i) & 255); + if(byte >= 128) { + byte -= 256; + } + bytes.writeInt8(byte); + } + var resBytes = bytes.getBytes(); + me.onBinaryData(resBytes); + } + else if ( s == null ) { + me.req = null; + me.onError("Failed to connect or resolve host"); + } + else switch( s ) { + case 12029: + me.req = null; + me.onError("Failed to connect to host"); + case 12007: + me.req = null; + me.onError("Unknown host"); + default: + me.req = null; + me.responseData = r.responseText; + me.onError("Http Error #"+r.status); + } + }; + if( async ) + r.onreadystatechange = onreadystatechange; + var uri = postData; + var jsData = binaryPostData; + if( jsData != null ) + post = true; + else for( p in params ) { + if( uri == null ) + uri = ""; + else + uri += "&"; + uri += StringTools.urlEncode(p.param)+"="+StringTools.urlEncode(p.value); + } + try { + if( post ) + r.open("POST",url,async); + else if( uri != null ) { + var question = url.split("?").length <= 1; + r.open("GET",url+(if( question ) "?" else "&")+uri,async); + uri = null; + } else + r.open("GET",url,async); + } catch( e : Dynamic ) { + me.req = null; + onError(e.toString()); + return; + } + + //XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com] + req.overrideMimeType("text\\/plain; charset=x-user-defined"); + + #if (haxe_ver >= 3.3) + r.withCredentials = me.withCredentials; + #end + if( !Lambda.exists(headers, function(h) return h.header == "Content-Type") && post && postData == null ) + r.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); + + for( h in headers ) + r.setRequestHeader(h.header,h.value); + + if( jsData != null ) { + r.send(new js.html.Uint8Array(jsData.getData())); + } else { + r.send(uri); + } + + if( !async ) + onreadystatechange(null); + } + #elseif nodejs + public override function request( ?post : Bool ) : Void { + + var url_regexp = ~/^(https?:\/\/)?([a-zA-Z\.0-9_-]+)(:[0-9]+)?(.*)$/; + if( !url_regexp.match(url) ) { + onError("Invalid URL"); + return; + } + var ssl = (url_regexp.matched(1) == "https://"); + var host = url_regexp.matched(2); + var portString = url_regexp.matched(3); + var request = url_regexp.matched(4); + if( request == "" ) + request = "/"; + var port = if ( portString == null || portString == "" ) ssl ? 443 : 80 else Std.parseInt(portString.substr(1, portString.length - 1)); + + var options = { + "hostname":host, + "port":port, + "path":request, + "method":post ? "POST" : "GET", + "agent":false, + "withCredentials":#if (haxe_ver >= 3.3) me.withCredentials #else false #end + }; + + var headersCode = ""; + for( h in headers ) + headersCode += 'req.setHeader("${h.header}","${h.value}");'; + + // stringify data + var sendCode = ""; + var data = binaryPostData; + + if(data != null) { + var bufStr = haxe.Json.stringify(js.node.buffer.Buffer.hxFromBytes(data)).replace("'", "\\'"); + sendCode = "var dataObj = JSON.parse('" + bufStr + "', " + + " function(key, value) {" + + "return value && value.type === 'Buffer'" + + "? new Buffer(value.data)" + + ": value;" + + "});"; + sendCode += "req.write(dataObj);"; + headersCode += 'req.setHeader("Content-Length",${data.length});'; + } else { + headersCode += 'req.setHeader("Content-Length", 0);'; + } + + var responseEncoding = 'binary'; + + // The async request the other Node process executes + var execString = "var http = require('http'), https = require('https'), fs = require('fs');" + + "var doRequest = http" + (ssl ? "s" : "") + ".request;" + + "var options = " + haxe.Json.stringify(options) + ";" + + "var responseText = '';" + + "var req = doRequest(options, function(response) {" + + "response.setEncoding(" + (responseEncoding != null ? "'" + responseEncoding + "'" : responseEncoding) + ");" + + "response.on('data', function(chunk) {" + + " responseText += chunk;" + + "});" + + "response.on('end', function() {" + + "if(responseText.length) {" + + " responseText = JSON.stringify(new Buffer(responseText, " + (responseEncoding != null ? "'" + responseEncoding + "'" : responseEncoding) + "));" + + "}" + + "process.stdout.write(JSON.stringify({err: null, data: {statusCode: response.statusCode, headers: response.headers, text: responseText}}));" + + "});" + + "response.on('error', function(error) {" + + "process.stdout.write(JSON.stringify({err: error, errorMessage : error.message}));" + + "});" + + "}).on('error', function(error) {" + + "process.stdout.write(JSON.stringify({err: error, errorMessage : error.message}));" + + "});" + + headersCode + + sendCode + + "req.end();"; --- End diff -- Did you think about possible code injection issues? How do we prevent that? Tested? > haxe js/nodejs client > --------------------- > > Key: THRIFT-3876 > URL: https://issues.apache.org/jira/browse/THRIFT-3876 > Project: Thrift > Issue Type: Improvement > Components: Haxe - Library > Reporter: Oleksii Prudkyi > Assignee: Oleksii Prudkyi > -- This message was sent by Atlassian JIRA (v6.3.4#6332)