private async void sendRequest(HttpClient client, HttpRequestMessage request, dynamic callback) { HttpResponseMessage response; try { response = await client.SendAsync(request); } catch (HttpRequestException x) { dynamic exp = new JsErrorBuilder(x).SetErrorCode((int)ErrorCodes.NetworkOffline).Build(); dynamic rz = engine.ManticoreJsObject._.construct(); callback(exp, rz); return; } dynamic responseInfo = engine.ManticoreJsObject._.construct(); dynamic headers = null; foreach (var kv in response.Headers) { if (headers == null) { headers = engine.ManticoreJsObject._.construct(); } headers[kv.Key] = engine.Converter.ToJsArray(kv.Value.ToList(), (v) => v.ToString()); } foreach (var kv in response.Content.Headers) { if (headers == null) { headers = engine.ManticoreJsObject._.construct(); } headers[kv.Key] = engine.Converter.ToJsArray(kv.Value.ToList(), (v) => v.ToString()); } responseInfo.headers = headers; responseInfo.status = (int)response.StatusCode; // TODO figure out how to sneak this wait into the readers var responseBytes = await response.Content.ReadAsByteArrayAsync(); responseInfo.json = new Func <dynamic>(() => { try { return(engine.v8.Script.JSON.parse(Encoding.UTF8.GetString(responseBytes))); } catch (ScriptEngineException se) { return(new JsErrorBuilder(se).Build()); } }); responseInfo.text = new Func <dynamic>(() => Encoding.UTF8.GetString(responseBytes)); responseInfo.body = new Func <dynamic>(() => Convert.ToBase64String(responseBytes)); callback(null, responseInfo); }
private async void sendRequest(ManticoreEngine engine, int timeout, HttpClient client, HttpRequestMessage request, JsValue callback) { var responseInfo = engine.CreateJsObject(); HttpResponseMessage response = null; CancellationTokenSource cts = new CancellationTokenSource(timeout); try { response = await client.SendRequestAsync(request, HttpCompletionOption.ResponseContentRead).AsTask(cts.Token); } catch (Exception x) { var ei = new JsErrorBuilder(engine, x).Build(); responseInfo.FastAddProperty("error", ei, false, true, false); } if (response != null && response.Headers.Count > 0) { var headerCollection = engine.CreateJsObject(); foreach (var kv in response.Headers) { try { headerCollection.FastAddProperty(kv.Key, new JsValue(kv.Value), false, true, false); } catch (ArgumentException) { // Swallow duplicate headers for now. } } responseInfo.FastAddProperty("headers", headerCollection, false, true, false); } byte[] binaryResult = null; if (response != null) { responseInfo.FastAddProperty("status", new JsValue((int)response.StatusCode), false, true, false); // TODO find a way to sneak this wait into the gap between returning and asking for the results // json/body/text signatures probably need to change to take a callback. binaryResult = (await response.Content.ReadAsBufferAsync()).ToArray(); } engine.Js(() => { responseInfo.FastAddProperty("json", engine.AsJsFunction((thisObject, args) => { return(engine.jsEngine.Json.Parse(JsValue.Null, new JsValue[] { Encoding.UTF8.GetString(binaryResult, 0, binaryResult.Length) })); }), false, false, false); responseInfo.FastAddProperty("body", engine.AsJsFunction((thisObject, args) => { return(engine.jsEngine.Json.Parse(JsValue.Null, new JsValue[] { Convert.ToBase64String(binaryResult) })); }), false, false, false); responseInfo.FastAddProperty("text", engine.AsJsFunction((thisObject, args) => { return(new JsValue(Encoding.UTF8.GetString(binaryResult, 0, binaryResult.Length))); }), false, false, false); callback.As <FunctionInstance>().Call(engine.ManticoreJsObject, new JsValue[] { JsValue.Null, responseInfo }); }); }
public void Fetch(ManticoreEngine engine, JsValue optionsValue, JsValue callback) { var options = optionsValue.As <ObjectInstance>(); JsValue rawBody = options.Get("nativeBody").As <FunctionInstance>().Call(options, ManticoreEngine.EmptyArgs); var hasBody = rawBody.IsString() && rawBody.AsString().Length > 0; var request = (HttpWebRequest)WebRequest.Create(options.Get("url").AsString()); request.Method = "GET"; if (options.HasProperty("method")) { request.Method = options.Get("method").AsString(); } if (options.HasProperty("headers")) { var headers = options.Get("headers").AsObject(); var raw = headers.Get("raw").As <FunctionInstance>().Call(headers, ManticoreEngine.EmptyArgs); if (raw.IsObject()) { foreach (var p in raw.AsObject().GetOwnProperties()) { if (p.Key.Equals("Content-Type", StringComparison.OrdinalIgnoreCase)) { if (hasBody) { request.ContentType = p.Value.Value.Value.AsString(); } } else if (p.Key.Equals("If-Modified-Since", StringComparison.OrdinalIgnoreCase)) { request.IfModifiedSince = DateTime.Parse(p.Value.Value.Value.AsString()); } else { request.Headers.Add(p.Key, p.Value.Value.Value.AsString()); } } } } if (hasBody) { var body = rawBody.AsString(); byte[] bodyBytes; if (options.HasProperty("isBase64") && options.Get("isBase64").AsBoolean()) { bodyBytes = Convert.FromBase64String(body); } else { bodyBytes = Encoding.UTF8.GetBytes(body); } request.ContentLength = bodyBytes.Length; var errorInstance = JsValue.Null; try { var rqStream = request.GetRequestStream(); rqStream.Write(bodyBytes, 0, bodyBytes.Length); rqStream.Close(); } catch (Exception x) { // TODO fire this log into JS? manticore.onError()? Log("error", x.ToString(), JsValue.Null); var errorBuilder = new JsErrorBuilder(engine, x); if (x is WebException) { errorBuilder.SetErrorCode((int)ErrorCodes.NetworkOffline); } errorInstance = errorBuilder.Build(); } if (errorInstance != JsValue.Null) { engine.Js(() => { callback.As <FunctionInstance>().Call(engine.ManticoreJsObject, new[] { errorInstance, JsValue.Null }); }); return; } } sendRequest(engine, request, callback); }
private void sendRequest(ManticoreEngine engine, HttpWebRequest request, JsValue callback) { request.BeginGetResponse((asyncResult) => { HttpWebResponse response = null; var errorInstance = JsValue.Null; try { response = (HttpWebResponse)request.EndGetResponse(asyncResult); } catch (WebException e) { if (e.Status == WebExceptionStatus.ProtocolError) //Response was received from server but indicated protocol level error { response = (HttpWebResponse)e.Response; } else { errorInstance = new JsErrorBuilder(engine, e).SetErrorCode((int)ErrorCodes.NetworkOffline).Build(); } } if (response == null) { engine.Js(() => { callback.As <FunctionInstance>().Call(engine.ManticoreJsObject, new[] { errorInstance, JsValue.Null }); }); return; } var responseInfo = engine.CreateJsObject(); if (response.Headers.Count > 0) { var headerCollection = engine.CreateJsObject(); foreach (var kv in response.Headers.AllKeys) { headerCollection.FastAddProperty(kv, new JsValue(response.Headers[kv]), false, true, false); } responseInfo.FastAddProperty("headers", headerCollection, false, true, false); } responseInfo.FastAddProperty("status", new JsValue((int)response.StatusCode), false, true, false); // TODO find a way to sneak this wait into the gap between returning and asking for the results // json/body/text signatures probably need to change to take a callback. var memStream = new MemoryStream(); response.GetResponseStream().CopyTo(memStream); var binaryResult = memStream.ToArray(); responseInfo.FastAddProperty("json", engine.AsJsFunction((thisObject, args) => { return(engine.jsEngine.Json.Parse(JsValue.Null, new JsValue[] { Encoding.UTF8.GetString(binaryResult) })); }), false, false, false); responseInfo.FastAddProperty("body", engine.AsJsFunction((thisObject, args) => { return(engine.jsEngine.Json.Parse(JsValue.Null, new JsValue[] { Convert.ToBase64String(binaryResult) })); }), false, false, false); responseInfo.FastAddProperty("text", engine.AsJsFunction((thisObject, args) => { return(new JsValue(Encoding.UTF8.GetString(binaryResult))); }), false, false, false); engine.Js(() => { callback.As <FunctionInstance>().Call(engine.ManticoreJsObject, new[] { errorInstance, responseInfo }); }); }, null); }