/// <summary> /// Parses url encoded form data /// </summary> /// <returns>An awaitable task.</returns> /// <param name="reader">The stream to read from.</param> /// <param name="config">The server configuration.</param> /// <param name="idletime">The maximum idle time.</param> /// <param name="timeouttask">A task that signals request timeout.</param> /// <param name="stoptask">A task that signals server stop.</param> internal async Task ParseFormData(BufferedStreamReader reader, ServerConfig config, TimeSpan idletime, Task timeouttask, Task stoptask) { if (string.Equals("application/x-www-form-urlencoded", this.ContentType)) { if (this.ContentLength != 0) { if (this.ContentLength > config.MaxUrlEncodedFormSize) { throw new HttpException(HttpStatusCode.PayloadTooLarge); } ParseQueryString( System.Text.Encoding.ASCII.GetString( this.ContentLength > 0 ? await reader.RepeatReadAsync(this.ContentLength, idletime, timeouttask, stoptask) : await reader.ReadUntilCrlfAsync(config.MaxRequestLineSize, config.MaxUrlEncodedFormSize, idletime, timeouttask, stoptask) ), this.Form); } this.Body = new LimitedBodyStream(reader, 0, idletime, timeouttask, stoptask); } else if (RequestUtility.IsMultipartRequest(this.ContentType) && this.ContentLength > 0 && this.ContentLength < config.MaxUrlEncodedFormSize && config.AutoParseMultipartFormData) { await ParseMultiPart( async (headers, stream) => { var dispositionItems = RequestUtility.SplitHeaderLine(headers["Content-Disposition"]); if (!string.Equals(dispositionItems.FirstOrDefault().Key, "form-data", StringComparison.OrdinalIgnoreCase)) { throw new HttpException(HttpStatusCode.BadRequest); } var name = RequestUtility.GetHeaderComponent(headers["Content-Disposition"], "name"); if (string.IsNullOrWhiteSpace("name")) { throw new HttpException(HttpStatusCode.BadRequest); } var filename = RequestUtility.GetHeaderComponent(headers["Content-Disposition"], "filename"); var charset = RequestUtility.GetHeaderComponent(headers["Content-Type"], "charset") ?? "ascii"; if (string.IsNullOrWhiteSpace(filename)) { using (var sr = new StreamReader(stream, RequestUtility.GetEncodingForCharset(charset))) { var rtask = sr.ReadToEndAsync(); var rt = await Task.WhenAny(timeouttask, stoptask, rtask); if (rt != rtask) { if (rt == stoptask) { throw new TaskCanceledException(); } else { throw new HttpException(HttpStatusCode.RequestTimeout); } } this.Form[name] = rtask.Result; } } else { var me = new MultipartItem(headers) { Name = name, Filename = filename, Data = new MemoryStream() }; Task rtask; Task rt; using (var cs = new CancellationTokenSource(idletime)) { rtask = stream.CopyToAsync(me.Data, 8 * 1024, cs.Token); rt = await Task.WhenAny(timeouttask, stoptask, rtask); } if (rt != rtask) { if (rt == stoptask) { throw new TaskCanceledException(); } else { throw new HttpException(HttpStatusCode.RequestTimeout); } } rtask.GetAwaiter().GetResult(); me.Data.Position = 0; this.Files.Add(me); } }, reader, config, idletime, timeouttask, stoptask ); this.Body = new LimitedBodyStream(reader, 0, idletime, timeouttask, stoptask); } else { this.Body = new LimitedBodyStream(reader, this.ContentLength, idletime, timeouttask, stoptask); } }