diff --git a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj index 023908e..b1e7865 100644 --- a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj +++ b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Apache.OpenWhisk.Runtime.Common.csproj @@ -18,6 +18,7 @@ net6.0 + enable diff --git a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/HttpResponseExtension.cs b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/HttpResponseExtension.cs index 4f63bd0..8f97628 100644 --- a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/HttpResponseExtension.cs +++ b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/HttpResponseExtension.cs @@ -27,15 +27,14 @@ public static class HttpResponseExtension { public static async Task WriteResponse(this HttpResponse response, int code, string content) { - byte[] bytes = Encoding.UTF8.GetBytes(content); - response.ContentLength = bytes.Length; + response.ContentLength = Encoding.UTF8.GetByteCount(content); response.StatusCode = code; await response.WriteAsync(content); } public static async Task WriteError(this HttpResponse response, string errorMessage) { - JObject message = new JObject {{"error", new JValue(errorMessage)}}; + JObject message = new() {{"error", new JValue(errorMessage)}}; await WriteResponse(response, 502, JsonConvert.SerializeObject(message)); } diff --git a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs index 0a1a054..56f84bf 100644 --- a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs +++ b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs @@ -21,7 +21,6 @@ using System.Reflection; using System.Threading; using System.Threading.Tasks; -using System.Collections.Generic; using Microsoft.AspNetCore.Http; using Newtonsoft.Json.Linq; @@ -29,23 +28,23 @@ namespace Apache.OpenWhisk.Runtime.Common { public class Init { - private readonly SemaphoreSlim _initSemaphoreSlim = new SemaphoreSlim(1, 1); + private readonly SemaphoreSlim _initSemaphoreSlim = new(initialCount: 1, maxCount: 1); + private Type? _type; + private MethodInfo? _method; + private ConstructorInfo? _constructor; + private bool _awaitableMethod; public bool Initialized { get; private set; } - private Type Type { get; set; } - private MethodInfo Method { get; set; } - private ConstructorInfo Constructor { get; set; } - private bool AwaitableMethod { get; set; } public Init() { Initialized = false; - Type = null; - Method = null; - Constructor = null; + _type = null; + _method = null; + _constructor = null; } - public async Task HandleRequest(HttpContext httpContext) + public async Task HandleRequest(HttpContext httpContext) { await _initSemaphoreSlim.WaitAsync(); try @@ -54,58 +53,52 @@ public async Task HandleRequest(HttpContext httpContext) { 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)); + return new Run(_type, _method, _constructor, _awaitableMethod); } - string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync(); + using StreamReader reader = new(httpContext.Request.Body); + string body = await reader.ReadToEndAsync(); JObject inputObject = JObject.Parse(body); - if (!inputObject.ContainsKey("value")) + if (!inputObject.TryGetValue("value", out JToken? message) || message is not JObject valueObj) { await httpContext.Response.WriteError("Missing main/no code to execute."); - return (null); + return null; } - JToken message = inputObject["value"]; + string main = valueObj.TryGetValue("main", out JToken? mainToken) ? mainToken.ToString() : string.Empty; + string code = valueObj.TryGetValue("code", out JToken? codeToken) ? codeToken.ToString() : string.Empty; + bool binary = valueObj.TryGetValue("binary", out JToken? binaryToken) && binaryToken.ToObject(); - if (message["main"] == null || message["binary"] == null || message["code"] == null) + if (string.IsNullOrWhiteSpace(main) || string.IsNullOrWhiteSpace(code)) { await httpContext.Response.WriteError("Missing main/no code to execute."); - return (null); + return null; } - string main = message["main"].ToString(); - - bool binary = message["binary"].ToObject(); - if (!binary) { await httpContext.Response.WriteError("code must be binary (zip file)."); - return (null); + return null; } string[] mainParts = main.Split("::"); if (mainParts.Length != 3) { await httpContext.Response.WriteError("main required format is \"Assembly::Type::Function\"."); - return (null); + 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); - } - } + using MemoryStream stream = new(Convert.FromBase64String(code)); + using ZipArchive archive = new(stream); + archive.ExtractToDirectory(tempPath); } catch (Exception) { await httpContext.Response.WriteError("Unable to decompress package."); - return (null); + return null; } Environment.CurrentDirectory = tempPath; @@ -117,31 +110,30 @@ public async Task HandleRequest(HttpContext httpContext) if (!File.Exists(assemblyPath)) { await httpContext.Response.WriteError($"Unable to locate requested assembly (\"{assemblyFile}\")."); - return (null); + return null; } try { // Export init arguments as environment variables - if (message["env"] != null && message["env"].HasValues) + if (valueObj.TryGetValue("env", out JToken? values) && values is JObject dictEnv) { - Dictionary dictEnv = message["env"].ToObject>(); - foreach (KeyValuePair entry in dictEnv) { + foreach ((string envKey, JToken? envVal) 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); + // If envVal is null or the empty string, the variable is not set + Environment.SetEnvironmentVariable(envKey, envVal?.ToString()); } } Assembly assembly = Assembly.LoadFrom(assemblyPath); - Type = assembly.GetType(mainParts[1]); - if (Type == null) + _type = assembly.GetType(mainParts[1]); + if (_type == null) { await httpContext.Response.WriteError($"Unable to locate requested type (\"{mainParts[1]}\")."); - return (null); + return null; } - Method = Type.GetMethod(mainParts[2]); - Constructor = Type.GetConstructor(Type.EmptyTypes); + _method = _type.GetMethod(mainParts[2]); + _constructor = _type.GetConstructor(Type.EmptyTypes); } catch (Exception ex) { @@ -151,26 +143,26 @@ await httpContext.Response.WriteError(ex.Message + ", " + ex.StackTrace #endif ); - return (null); + return null; } - if (Method == null) + if (_method == null) { await httpContext.Response.WriteError($"Unable to locate requested method (\"{mainParts[2]}\")."); - return (null); + return null; } - if (Constructor == null) + if (_constructor == null) { await httpContext.Response.WriteError($"Unable to locate appropriate constructor for (\"{mainParts[1]}\")."); - return (null); + return null; } Initialized = true; - AwaitableMethod = (Method.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null); + _awaitableMethod = _method.ReturnType.GetMethod(nameof(Task.GetAwaiter)) != null; - return (new Run(Type, Method, Constructor, AwaitableMethod)); + return new Run(_type, _method, _constructor, _awaitableMethod); } catch (Exception ex) { @@ -181,7 +173,7 @@ await httpContext.Response.WriteError(ex.Message #endif ); Startup.WriteLogMarkers(); - return (null); + return null; } finally { diff --git a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs index 0ee99ce..13e1eeb 100644 --- a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs +++ b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Run.cs @@ -26,12 +26,12 @@ namespace Apache.OpenWhisk.Runtime.Common { public class Run { - private readonly Type _type; - private readonly MethodInfo _method; - private readonly ConstructorInfo _constructor; + private readonly Type? _type; + private readonly MethodInfo? _method; + private readonly ConstructorInfo? _constructor; private readonly bool _awaitableMethod; - public Run(Type type, MethodInfo method, ConstructorInfo constructor, bool awaitableMethod) + public Run(Type? type, MethodInfo? method, ConstructorInfo? constructor, bool awaitableMethod) { _type = type; _method = method; @@ -49,12 +49,13 @@ public async Task HandleRequest(HttpContext httpContext) try { - string body = await new StreamReader(httpContext.Request.Body).ReadToEndAsync(); + using StreamReader reader = new(httpContext.Request.Body); + string body = await reader.ReadToEndAsync(); - JObject inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body); + JObject? inputObject = string.IsNullOrEmpty(body) ? null : JObject.Parse(body); - JObject valObject = null; - JArray valArray = null; + JObject? valObject = null; + JArray? valArray = null; if (inputObject != null) { @@ -66,7 +67,7 @@ public async Task HandleRequest(HttpContext httpContext) if (token.Path.Equals("value", StringComparison.InvariantCultureIgnoreCase)) continue; string envKey = $"__OW_{token.Path.ToUpperInvariant()}"; - string envVal = token.First.ToString(); + string? envVal = token.First?.ToString(); Environment.SetEnvironmentVariable(envKey, envVal); //Console.WriteLine($"Set environment variable \"{envKey}\" to \"{envVal}\"."); } @@ -81,24 +82,24 @@ await Console.Error.WriteLineAsync( } } - object owObject = _constructor.Invoke(new object[] { }); + object owObject = _constructor.Invoke(Array.Empty()); try { - JContainer output; + JContainer? output; if(_awaitableMethod) { if (valObject != null) { - output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valObject}); + output = (JContainer?) await (dynamic?) _method.Invoke(owObject, new object?[] {valObject}); } else { - output = (JContainer) await (dynamic) _method.Invoke(owObject, new object[] {valArray}); + output = (JContainer?) await (dynamic?) _method.Invoke(owObject, new object?[] {valArray}); } } else { if (valObject != null) { - output = (JContainer) _method.Invoke(owObject, new object[] {valObject}); + output = (JContainer?) _method.Invoke(owObject, new object?[] {valObject}); } else { - output = (JContainer) _method.Invoke(owObject, new object[] {valArray}); + output = (JContainer?) _method.Invoke(owObject, new object?[] {valArray}); } } diff --git a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Startup.cs b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Startup.cs index 9851e54..e8848bb 100644 --- a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Startup.cs +++ b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Startup.cs @@ -31,10 +31,10 @@ public static void WriteLogMarkers() public void Configure(IApplicationBuilder app) { - PathString initPath = new PathString("/init"); - PathString runPath = new PathString("/run"); - Init init = new Init(); - Run run = null; + PathString initPath = new("/init"); + PathString runPath = new("/run"); + Init init = new(); + Run? run = null; app.Run(async (httpContext) => { if (httpContext.Request.Path.Equals(initPath)) diff --git a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj index 1bcbb35..49af8c7 100644 --- a/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj +++ b/core/net6.0/proxy/Apache.OpenWhisk.Runtime.Dotnet.Minimal/Apache.OpenWhisk.Runtime.Dotnet.Minimal.csproj @@ -19,6 +19,7 @@ Exe net6.0 + enable