/// <summary> /// Modifies our application startup to enable CSRF, and reparse thrown exceptions into messages and status codes. /// </summary> /// <remarks> /// To use this functionality, within every 'form' block, after all the inputs add '@Html.AntiForgeryToken()'. /// Then, within your POST reception, call 'this.ValidateCsrfToken();, catch the CsrfValidationException, and handle the result appropriately. /// </remarks> protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines) { base.ApplicationStartup(container, pipelines); Csrf.Enable(pipelines); pipelines.BeforeRequest += (ctx) => { NancyContext context = ctx as NancyContext; logger.Info(context.Request.UserHostAddress + ": " + context.Request.Url); if (Global.SystemStats.AddCall(context.Request.UserHostAddress)) { logger.Info($"Throttling a request from {context.Request.UserHostAddress}"); return(this.GenerateJsonException(new ExcessiveQueriesException(), HttpStatusCode.TooManyRequests)); } // Technically this is 7.4% over 1 MiB. I'm not going to be pedantic. int maxIterations = 12; int hundredKiB = 100 * 1024; byte[] hundredK = new byte[hundredKiB]; RequestStream requestStream = context.Request.Body; for (int i = 0; i < maxIterations; i++) { // This unfortunately means we're processing the request stream twice. if (requestStream.Read(hundredK, 0, hundredKiB) != hundredKiB) { // The request is under 1 MiB, so continue processing. Reset the stream so deserializing the JSON works. requestStream.Seek(0, SeekOrigin.Begin); return(null); } } logger.Info($"Request from {context.Request.UserHostAddress} to {context.Request.Url} over 1 MiB"); return(this.GenerateJsonException(new ExcessiveNapackException(), HttpStatusCode.BadRequest)); }; StaticConfiguration.DisableErrorTraces = false; pipelines.OnError += (context, exception) => { HttpStatusCode code = HttpStatusCode.InternalServerError; Exception parsedException = exception as Exception; if (parsedException != null) { if (!exceptionStatusCodeMapping.TryGetValue(parsedException.GetType(), out code)) { code = HttpStatusCode.InternalServerError; } } else { parsedException = new Exception("Unable to decode the detected exception!"); } logger.Warn($"Hit a {parsedException.GetType()} exception: {parsedException.Message}"); return(this.GenerateJsonException(parsedException, code)); }; }
public static async Task <string> AsStringAsync(this RequestStream request, CancellationToken ct) { using (var reader = new StreamReader(request)) { var result = await reader.ReadToEndAsync(); ct.ThrowIfCancellationRequested(); // set streams position to beginning request.Seek(0, SeekOrigin.Begin); return(result); } }