public async Task HandleRequest()

in core/net6.0/proxy/Apache.OpenWhisk.Runtime.Common/Init.cs [48:190]


        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();
            }
        }