BuildConfigurationZipArchive( string frontendWebElmMakeCommandAppendix) { var currentDirectory = Environment.CurrentDirectory; Console.WriteLine("The currentDirectory is '" + currentDirectory + "'."); var elmAppFilesBeforeLowering = ElmApp.ToFlatDictionaryWithPathComparer( ElmApp.FilesFilteredForElmApp( Filesystem.GetAllFilesFromDirectory(Path.Combine(currentDirectory, ElmAppSubdirectoryName))) .Select(filePathAndContent => ((IImmutableList <string>)filePathAndContent.filePath.Split(new[] { '/', '\\' }).ToImmutableList(), filePathAndContent.fileContent))); Console.WriteLine("I found " + elmAppFilesBeforeLowering.Count + " files to build the Elm app."); var elmAppContainsFrontend = elmAppFilesBeforeLowering.ContainsKey(FrontendElmAppRootFilePath); Console.WriteLine("This Elm app contains " + (elmAppContainsFrontend ? "a" : "no") + " frontend at '" + string.Join("/", FrontendElmAppRootFilePath) + "'."); var loweredElmAppFiles = ElmApp.AsCompletelyLoweredElmApp( elmAppFilesBeforeLowering, ElmAppInterfaceConfig.Default); byte[] frontendWebFile = null; if (elmAppContainsFrontend) { var frontendWebHtml = ProcessFromElm019Code.CompileElmToHtml( loweredElmAppFiles, FrontendElmAppRootFilePath, frontendWebElmMakeCommandAppendix); frontendWebFile = Encoding.UTF8.GetBytes(frontendWebHtml); } WebAppConfigurationJsonStructure jsonStructure = null; var jsonFileSearchPath = Path.Combine(currentDirectory, "elm-fullstack.json"); if (File.Exists(jsonFileSearchPath)) { Console.WriteLine("I found a file at '" + jsonFileSearchPath + "'. I use this to build the configuration."); var jsonFile = File.ReadAllBytes(jsonFileSearchPath); jsonStructure = JsonConvert.DeserializeObject <WebAppConfigurationJsonStructure>(Encoding.UTF8.GetString(jsonFile)); } else { Console.WriteLine("I did not find a file at '" + jsonFileSearchPath + "'. I build the configuration without the 'elm-fullstack.json'."); } var staticFiles = frontendWebFile == null? Array.Empty <(IImmutableList <string> name, IImmutableList <byte> content)>() : new[] { (name : (IImmutableList <string>)ImmutableList.Create(FrontendWebStaticFileName), (IImmutableList <byte>)frontendWebFile.ToImmutableList()) };
static RateLimitMutableContainer BuildRateLimitContainerForClient(WebAppConfigurationJsonStructure jsonStructure) { if (jsonStructure?.singleRateLimitWindowPerClientIPv4Address == null) { return(null); } return(new RateLimitMutableContainer(new RateLimitStateSingleWindow { limit = jsonStructure.singleRateLimitWindowPerClientIPv4Address.limit, windowSize = jsonStructure.singleRateLimitWindowPerClientIPv4Address.windowSizeInMs, })); }
static async Task RateLimitMiddlewareFromWebAppConfig( WebAppConfigurationJsonStructure webAppConfig, HttpContext context, Func <Task> next) { string ClientId() { const string defaultClientId = "MapToIPv4-failed"; try { return(context.Connection.RemoteIpAddress?.MapToIPv4().ToString() ?? defaultClientId); } catch { return(defaultClientId); } } var rateLimitFromClientId = context.RequestServices.GetService <ClientsRateLimitStateContainer>().RateLimitFromClientId; var clientRateLimitState = rateLimitFromClientId.GetOrAdd( ClientId(), _ => BuildRateLimitContainerForClient(webAppConfig)); if (clientRateLimitState?.AttemptPass(Configuration.GetDateTimeOffset(context).ToUnixTimeMilliseconds()) ?? true) { await next?.Invoke(); return; } context.Response.StatusCode = 429; await context.Response.WriteAsync(""); return; }
static public async Task MiddlewareFromWebAppConfig( WebAppConfigurationJsonStructure webAppConfig, HttpContext context, Func <Task> next) => await RateLimitMiddlewareFromWebAppConfig(webAppConfig, context, next);