public async Task HandleRequest(HttpContext httpContext) { if (_type == null || _method == null || _constructor == null) { await httpContext.Response.WriteError("Cannot invoke an uninitialized action."); return; } try { string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync(); JObject inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body); JObject valObject = null; if (inputObject != null) { valObject = inputObject["value"] as JObject; foreach (JToken token in inputObject.Children()) { try { if (token.Path.Equals("value", StringComparison.InvariantCultureIgnoreCase)) { continue; } string envKey = $"__OW_{token.Path.ToUpperInvariant()}"; string envVal = token.First.ToString(); Environment.SetEnvironmentVariable(envKey, envVal); //Console.WriteLine($"Set environment variable \"{envKey}\" to \"{envVal}\"."); } catch (Exception) { await Console.Error.WriteLineAsync( $"Unable to set environment variable for the \"{token.Path}\" token."); } } } object owObject = _constructor.Invoke(new object[] { }); try { JObject output = (JObject)_method.Invoke(owObject, new object[] { valObject }); if (output == null) { await httpContext.Response.WriteError("The action returned null"); Console.Error.WriteLine("The action returned null"); return; } await httpContext.Response.WriteResponse(200, output.ToString()); } catch (Exception ex) { Console.Error.WriteLine(ex.StackTrace); await httpContext.Response.WriteError(ex.Message #if DEBUG + ", " + ex.StackTrace #endif ); } } finally { Startup.WriteLogMarkers(); } }
public async Task HandleRequest(HttpContext httpContext) { if (_methodAsync == null && _method == null) { await httpContext.Response.WriteError("Cannot invoke an uninitialized action."); return; } try { //string body = JsonSerializer.Serialize( new HttpResponseExtension.Response("test") ); //httpContext.Response.StatusCode = 200; //httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount( body ); //await httpContext.Response.WriteAsync( body ); //return; //string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync(); //JObject inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body); //JObject valObject = null; //if (inputObject != null) //{ // valObject = inputObject["value"] as JObject; // foreach (JToken token in inputObject.Children()) // { // try // { // if (token.Path.Equals("value", StringComparison.InvariantCultureIgnoreCase)) // continue; // string envKey = $"__OW_{token.Path.ToUpperInvariant()}"; // string envVal = token.First.ToString(); // Environment.SetEnvironmentVariable(envKey, envVal); // //Console.WriteLine($"Set environment variable \"{envKey}\" to \"{envVal}\"."); // } // catch (Exception) // { // await Console.Error.WriteLineAsync( // $"Unable to set environment variable for the \"{token.Path}\" token."); // } // } //} try { if (_awaitableMethod) { await _methodAsync(httpContext); } else { _method(httpContext); } } catch (Exception ex) { Console.Error.WriteLine(ex.StackTrace); await httpContext.Response.WriteError(ex.Message #if DEBUG + ", " + ex.StackTrace #endif ); } } finally { Startup.WriteLogMarkers(); } }
public async Task <Run> HandleRequest(HttpContext httpContext) { await _initSemaphoreSlim.WaitAsync(); try { if (Initialized) { await httpContext.Response.WriteError("Cannot initialize the action more than once."); Console.Error.WriteLine("Cannot initialize the action more than once."); return(new Run(Type, Method, Constructor, AwaitableMethod)); } string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync(); JObject inputObject = JObject.Parse(body); if (!inputObject.ContainsKey("value")) { await httpContext.Response.WriteError("Missing main/no code to execute."); return(null); } JToken message = inputObject["value"]; if (message["main"] == null || message["binary"] == null || message["code"] == null) { await httpContext.Response.WriteError("Missing main/no code to execute."); return(null); } string main = message["main"].ToString(); bool binary = message["binary"].ToObject <bool>(); if (!binary) { await httpContext.Response.WriteError("code must be binary (zip file)."); return(null); } string[] mainParts = main.Split("::"); if (mainParts.Length != 3) { await httpContext.Response.WriteError("main required format is \"Assembly::Type::Function\"."); return(null); } string tempPath = Path.Combine(Environment.CurrentDirectory, Guid.NewGuid().ToString()); string base64Zip = message["code"].ToString(); try { using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(base64Zip))) { using (ZipArchive archive = new ZipArchive(stream)) { archive.ExtractToDirectory(tempPath); } } } catch (Exception) { await httpContext.Response.WriteError("Unable to decompress package."); return(null); } Environment.CurrentDirectory = tempPath; string assemblyFile = $"{mainParts[0]}.dll"; string assemblyPath = Path.Combine(tempPath, assemblyFile); if (!File.Exists(assemblyPath)) { await httpContext.Response.WriteError($"Unable to locate requested assembly (\"{assemblyFile}\")."); return(null); } try { // Export init arguments as environment variables if (message["env"] != null && message["env"].HasValues) { Dictionary <string, string> dictEnv = message["env"].ToObject <Dictionary <string, string> >(); foreach (KeyValuePair <string, string> entry in dictEnv) { // See https://docs.microsoft.com/en-us/dotnet/api/system.environment.setenvironmentvariable // If entry.Value is null or the empty string, the variable is not set Environment.SetEnvironmentVariable(entry.Key, entry.Value); } } Assembly assembly = Assembly.LoadFrom(assemblyPath); Type = assembly.GetType(mainParts[1]); if (Type == null) { await httpContext.Response.WriteError($"Unable to locate requested type (\"{mainParts[1]}\")."); return(null); } Method = Type.GetMethod(mainParts[2]); Constructor = Type.GetConstructor(Type.EmptyTypes); } catch (Exception ex) { Console.Error.WriteLine(ex.ToString()); await httpContext.Response.WriteError(ex.Message #if DEBUG + ", " + ex.StackTrace #endif ); return(null); } if (Method == null) { await httpContext.Response.WriteError($"Unable to locate requested method (\"{mainParts[2]}\")."); return(null); } if (Constructor == null) { await httpContext.Response.WriteError($"Unable to locate appropriate constructor for (\"{mainParts[1]}\")."); return(null); } Initialized = true; AwaitableMethod = (Method.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null); return(new Run(Type, Method, Constructor, AwaitableMethod)); } catch (Exception ex) { Console.Error.WriteLine(ex.StackTrace); await httpContext.Response.WriteError(ex.Message #if DEBUG + ", " + ex.StackTrace #endif ); Startup.WriteLogMarkers(); return(null); } finally { _initSemaphoreSlim.Release(); } }
public async Task <Run> HandleRequest(HttpContext httpContext) { await _initSemaphoreSlim.WaitAsync(); try { if (Initialized) { await httpContext.Response.WriteError("Cannot initialize the action more than once."); Console.Error.WriteLine("Cannot initialize the action more than once."); return(new Run(Type, Method, Constructor)); } string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync(); JObject inputObject = JObject.Parse(body); if (!inputObject.ContainsKey("value")) { await httpContext.Response.WriteError("Missing main/no code to execute."); return(null); } JToken message = inputObject["value"]; if (message["main"] == null || message["binary"] == null || message["code"] == null) { await httpContext.Response.WriteError("Missing main/no code to execute."); return(null); } string main = message["main"].ToString(); bool binary = message["binary"].ToObject <bool>(); if (!binary) { await httpContext.Response.WriteError("code must be binary (zip file)."); return(null); } string[] mainParts = main.Split("::"); if (mainParts.Length != 3) { await httpContext.Response.WriteError("main required format is \"Assembly::Type::Function\"."); return(null); } string base64Zip = message["code"].ToString(); string tempPath = Path.Combine(Environment.CurrentDirectory, Guid.NewGuid().ToString()); string tempFile = Path.GetTempFileName(); await File.WriteAllBytesAsync(tempFile, Convert.FromBase64String(base64Zip)); try { System.IO.Compression.ZipFile.ExtractToDirectory(tempFile, tempPath); } catch (Exception ex) { await httpContext.Response.WriteError("Unable to decompress package."); return(null); } finally { File.Delete(tempFile); } Environment.CurrentDirectory = tempPath; string assemblyFile = $"{mainParts[0]}.dll"; string assemblyPath = Path.Combine(tempPath, assemblyFile); if (!File.Exists(assemblyPath)) { await httpContext.Response.WriteError($"Unable to locate requested assembly (\"{assemblyFile}\")."); return(null); } try { Assembly assembly = Assembly.LoadFrom(assemblyPath); Type = assembly.GetType(mainParts[1]); if (Type == null) { await httpContext.Response.WriteError($"Unable to locate requested type (\"{mainParts[1]}\")."); return(null); } Method = Type.GetMethod(mainParts[2]); Constructor = Type.GetConstructor(Type.EmptyTypes); } catch (Exception ex) { Console.Error.WriteLine(ex.ToString()); await httpContext.Response.WriteError(ex.Message #if DEBUG + ", " + ex.StackTrace #endif ); return(null); } if (Method == null) { await httpContext.Response.WriteError($"Unable to locate requested method (\"{mainParts[2]}\")."); return(null); } if (Constructor == null) { await httpContext.Response.WriteError($"Unable to locate appropriate constructor for (\"{mainParts[1]}\")."); return(null); } Initialized = true; await httpContext.Response.WriteResponse(200, "OK"); return(new Run(Type, Method, Constructor)); } catch (Exception ex) { Console.Error.WriteLine(ex.StackTrace); await httpContext.Response.WriteError(ex.Message #if DEBUG + ", " + ex.StackTrace #endif ); Startup.WriteLogMarkers(); return(null); } finally { _initSemaphoreSlim.Release(); } }
public async Task <Run> HandleRequest(HttpContext httpContext) { await _initSemaphoreSlim.WaitAsync(); try { if (Initialized) { await httpContext.Response.WriteError("Cannot initialize the action more than once."); Console.Error.WriteLine("Cannot initialize the action more than once."); return(new Run(Method, AwaitableMethod)); } //string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync(); //MethodToAdd.Value methodToAdd = JsonSerializer.Deserialize<MethodToAdd>(body).value; //MethodToAdd.Value methodToAdd = JsonConvert.DeserializeObject<MethodToAdd>(body).value; //fastest with much lower memory usage MethodToAdd.Value methodToAdd = (await System.Text.Json.JsonSerializer.DeserializeAsync <MethodToAdd>(httpContext.Request.Body)).value; if (string.IsNullOrEmpty(methodToAdd.main) || string.IsNullOrEmpty(methodToAdd.code)) { await httpContext.Response.WriteError("Missing main/no code to execute."); return(null); } if (!methodToAdd.binary) { await httpContext.Response.WriteError("code must be binary (zip file)."); return(null); } string[] mainParts = methodToAdd.main.Split("::"); if (mainParts.Length != 3) { await httpContext.Response.WriteError("main required format is \"Assembly::Type::Function\"."); return(null); } string tempPath = Path.Combine(Environment.CurrentDirectory, Guid.NewGuid().ToString()); try { using (var zipStream = new MemoryStream(Convert.FromBase64String(methodToAdd.code))) using (var zip = new ZipArchive(zipStream)) { zip.ExtractToDirectory(tempPath); } } catch (Exception) { await httpContext.Response.WriteError("Unable to decompress package."); return(null); } Environment.CurrentDirectory = tempPath; string assemblyFile = $"{mainParts[0]}.dll"; string assemblyPath = Path.Combine(tempPath, assemblyFile); if (!File.Exists(assemblyPath)) { await httpContext.Response.WriteError($"Unable to locate requested assembly (\"{assemblyFile}\")."); return(null); } try { Assembly assembly = Assembly.LoadFrom(assemblyPath); Type = assembly.GetType(mainParts[1]); if (Type == null) { await httpContext.Response.WriteError($"Unable to locate requested type (\"{mainParts[1]}\")."); return(null); } Method = Type.GetMethod(mainParts[2]); } catch (Exception ex) { Console.Error.WriteLine(ex.ToString()); await httpContext.Response.WriteError(ex.Message #if DEBUG + ", " + ex.StackTrace #endif ); return(null); } if (Method == null) { await httpContext.Response.WriteError($"Unable to locate requested method (\"{mainParts[2]}\")."); return(null); } Initialized = true; AwaitableMethod = (Method.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null); //AwaitableMethod = Method.ReturnType == typeof(Task); return(new Run(Method, AwaitableMethod)); } catch (Exception ex) { Console.Error.WriteLine(ex.ToString()); await httpContext.Response.WriteError(ex.ToString() #if DEBUG + ", " + ex.StackTrace #endif ); Startup.WriteLogMarkers(); return(null); } finally { _initSemaphoreSlim.Release(); } }