public static void ParseResponseBody(ManticoreEngine engine, ObjectInstance response, String format, Stream byteStream)
 {
     if ("json".Equals(format, StringComparison.OrdinalIgnoreCase))
     {
         String json = new StreamReader(byteStream, Encoding.UTF8).ReadToEnd();
         if (json != null && json.Length > 0)
         {
             JsValue jsObject = engine.jsEngine.Json.Parse(JsValue.Null, new JsValue[] { json });
             response.FastAddProperty("body", jsObject, false, true, false);
         }
     }
     else if (!"binary".Equals(format, StringComparison.OrdinalIgnoreCase))
     {
         String bodyString = new StreamReader(byteStream, Encoding.UTF8).ReadToEnd();
         response.FastAddProperty("body", new JsValue(bodyString), false, true, false);
     }
     else
     {
         byte[] bytes = ReadAllBytes(byteStream);
         if (bytes != null && bytes.Length > 0)
         {
             response.FastAddProperty("body", new JsValue(Convert.ToBase64String(bytes)), false, true, false);
         }
     }
 }
Example #2
0
 public void Register(ManticoreEngine engine)
 {
     engine.ManticoreJsObject.FastAddProperty("_log",
                                              engine.AsJsFunction((thisObject, args) =>
     {
         JsValue extra = JsValue.Null;
         if (args.Length > 2)
         {
             extra = args[2];
         }
         Log(args[0].AsString(), args[1].AsString(), extra);
         return(JsValue.Undefined);
     }), true, false, false);
     engine.ManticoreJsObject.FastAddProperty("_setTimeout",
                                              engine.AsJsFunction((thisObject, args) =>
     {
         SetTimeout(engine, args[0].As <FunctionInstance>(), (int)args[1].AsNumber());
         return(JsValue.Undefined);
     }), true, false, false);
     engine.ManticoreJsObject.FastAddProperty("_fetch",
                                              engine.AsJsFunction((thisObject, args) =>
     {
         Task.Factory.StartNew(() =>
         {
             Fetch(engine, args[0], args[1]);
         });
         return(JsValue.Undefined);
     }), true, false, false);
 }
 internal ManticoreJsError(ManticoreEngine manticoreEngine, Exception ex, int?code = null)
     : base(manticoreEngine.jsEngine, ex.Message)
 {
     FastAddProperty("message", ex.Message, true, false, true);
     FastAddProperty("code", code.HasValue ? new JsValue(code.Value) : JsValue.Null, true, false, true);
     FastAddProperty("stack", ex.StackTrace, true, false, true);
     FastAddProperty("toString", manticoreEngine.AsJsFunction(((thisObj, args) => ex.ToString())), true, false, false);
 }
Example #4
0
        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 Register(ManticoreEngine engine)
 {
     this.engine = engine;
     engine.ManticoreJsObject._log        = new Action <String, String>((level, message) => log(level, message));
     engine.ManticoreJsObject._setTimeout = new Action <dynamic, int>((fn, msec) =>
     {
         setTimeout(fn, msec);
     });
     engine.ManticoreJsObject._fetch = new Action <dynamic, dynamic>((opts, cb) => this.fetch(opts, cb));
 }
Example #6
0
        public static void CreateManticoreEngine(String script, String name)
        {
            if (Engine != null && Engine.IsStarted)
            {
                throw new InvalidOperationException("You must shut down the existing engine before creating a new one.");
            }
            var e = new ManticoreEngine();

            e.Converter = new DefaultConverter <JsBackedObject>(e, (native) => native.impl, (jsErr) => new ManticoreException(jsErr));
            // Typically, you would add your own native method implementations to
            // the ManticoreJsObject here, before you load your script
            e.LoadScript(script, name);
            Engine = e;
        }
Example #7
0
        private async void SetTimeout(ManticoreEngine engine, FunctionInstance callback, int timeout)
        {
            await Task.Delay(TimeSpan.FromMilliseconds(timeout));

            engine.Js(() =>
            {
                try
                {
                    callback.Call(JsValue.Null, new JsValue[] { });
                }
                catch (Exception x)
                {
                    Debug.WriteLine(x);
                }
            });
        }
Example #8
0
 private void SetTimeout(ManticoreEngine engine, FunctionInstance callback, int timeout)
 {
     System.Timers.Timer timer = new System.Timers.Timer();
     // TODO not sure there may be a better way to emulate NextTick
     timer.Interval  = Math.Max(1, timeout);
     timer.AutoReset = false;
     timer.Elapsed  += (obj, args) =>
     {
         engine.Js(() =>
         {
             try
             {
                 callback.Call(JsValue.Null, new JsValue[] { });
             }
             catch (Exception x)
             {
                 // TODO perhaps throw this error INTO JS?
                 Log("error", x.ToString(), JsValue.Null);
             }
         });
     };
     timer.Start();
 }
 public static void ParseResponseBody(ManticoreEngine engine, dynamic responseInfo, String format, byte[] response)
 {
     if ("json".Equals(format, StringComparison.OrdinalIgnoreCase))
     {
         String json = Encoding.UTF8.GetString(response);
         if (json.Length > 0)
         {
             responseInfo.body = engine.v8.Script.JSON.parse(json);
         }
     }
     else if (!"binary".Equals(format, StringComparison.OrdinalIgnoreCase))
     {
         String bodyString = Encoding.UTF8.GetString(response);
         responseInfo.body = bodyString;
     }
     else
     {
         if (response.Length > 0)
         {
             responseInfo.body = Convert.ToBase64String(response);
         }
     }
 }
 public JsErrorBuilder(ManticoreEngine manticoreEngine, Exception ex)
 {
     _engine    = manticoreEngine;
     _exception = ex;
 }
Example #11
0
        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);
        }
Example #12
0
        public void Fetch(ManticoreEngine engine, JsValue optionsValue, JsValue callback)
        {
            var options        = optionsValue.As <ObjectInstance>();
            var httpBaseFilter = new HttpBaseProtocolFilter
            {
                AllowUI = false
            };
            var client = new HttpClient(httpBaseFilter);

            HttpMethod requestMethod = HttpMethod.Get;

            if (options.HasProperty("method"))
            {
                var method = options.Get("method").AsString();
                if (method != null)
                {
                    switch (method.ToLower())
                    {
                    case "delete":
                        requestMethod = HttpMethod.Delete;
                        break;

                    case "head":
                        requestMethod = HttpMethod.Head;
                        break;

                    case "options":
                        requestMethod = HttpMethod.Options;
                        break;

                    case "patch":
                        requestMethod = HttpMethod.Patch;
                        break;

                    case "post":
                        requestMethod = HttpMethod.Post;
                        break;

                    case "put":
                        requestMethod = HttpMethod.Put;
                        break;
                    }
                }
            }

            var urlString = options.Get("url").AsString();
            var rawBody   = options.Get("nativeBody").As <ScriptFunctionInstance>().Call(options, ManticoreEngine.EmptyArgs);
            var hasBody   = rawBody.IsString() && rawBody.AsString().Length > 0;
            var request   = new HttpRequestMessage(requestMethod, new Uri(urlString));

            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.Content.Headers.Add(p.Key, p.Value.Value.Value.AsString());
                            }
                        }
                        else
                        {
                            request.Headers.Add(p.Key, p.Value.Value.Value.AsString());
                        }
                    }
                }
            }

            if (hasBody)
            {
                if (options.HasProperty("isBase64") && options.Get("isBase64").AsBoolean())
                {
                    request.Content = new HttpBufferContent(Convert.FromBase64String(rawBody.AsString()).AsBuffer());
                }
                else
                {
                    request.Content = new HttpBufferContent(Encoding.UTF8.GetBytes(rawBody.AsString()).AsBuffer());
                }
            }

            int timeout = 60000;

            if (options.HasProperty("timeout") && options.Get("timeout").IsNumber())
            {
                timeout = (int)options.Get("timeout").AsNumber();
            }
            sendRequest(engine, timeout, client, request, callback);
        }
Example #13
0
        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);
        }
 /// <summary>
 /// One of the important goals of Manticore is to isolate the fact that you have chosen to use it
 /// for services you advertise to others (e.g. the SDK scenario). SO, you can't have your objects
 /// inherit from our base class. This converter constructor is your punishment. You need to provide
 /// us two simple lambdas - one that retrives the JS value from your objects and one that makes
 /// your exception class. This means that in most simple cases you won't have to derive from
 /// DefaultConverter, just create one.
 /// </summary>
 public DefaultConverter(ManticoreEngine engine, Func <JsBaseClass, dynamic> jsExtractor, Func <dynamic, Exception> jsException)
 {
     this.engine      = engine;
     this.jsExtractor = jsExtractor;
     this.jsException = jsException;
 }
 /// <summary>
 /// One of the important goals of Manticore is to isolate the fact that you have chosen to use it
 /// for services you advertise to others (e.g. the SDK scenario). SO, you can't have your objects
 /// inherit from our base class. This converter constructor is your punishment. You need to provide
 /// us two simple lambdas - one that retrives the JS value from your objects and one that makes
 /// your exception class. This means that in most simple cases you won't have to derive from
 /// DefaultConverter, just create one.
 /// </summary>
 public DefaultConverter(ManticoreEngine engine, Func <JsBaseClass, JsValue> jsExtractor, Func <ObjectInstance, Exception> jsException)
 {
     this.engine      = engine;
     this.jsExtractor = jsExtractor;
     this.jsException = jsException;
 }