public Task WriteAsync(Span <byte> data) { if (!HasStarted) { WriteBeginResponseHeaders(); } if (_autoChunk) { _outputFormatter.Append(data.Length, Format.Parsed.HexLowercase); _outputFormatter.Write(data); _outputFormatter.Write(_endChunkBytes); } else { _outputFormatter.Write(data); } return(_outputFormatter.FlushAsync()); }
public void CopyTo(bool chunk, WritableChannelFormatter outputFormatter) { foreach (var header in _headers) { outputFormatter.Write(_headersStartBytes); outputFormatter.Append(header.Key); outputFormatter.Write(_headersSeperatorBytes); outputFormatter.Append(header.Value.ToString()); } if (chunk) { outputFormatter.Write(_chunkedHeaderBytes); } outputFormatter.Write(_serverHeaderBytes); var date = _dateHeaderValueManager.GetDateHeaderValues().Bytes; outputFormatter.Write(date); outputFormatter.Write(_headersEndBytes); }
public async Task ProcessAllRequests() { Reset(); while (true) { var buffer = await _input.ReadAsync(); try { if (buffer.IsEmpty && _input.Reading.IsCompleted) { // We're done with this connection return; } Console.WriteLine($"Read: {buffer.Length} bytes"); Console.WriteLine(BitConverter.ToString(buffer.ToArray())); Console.WriteLine(buffer.GetAsciiString()); var result = _parser.ParseRequest(ref buffer); Console.WriteLine($"Result: {result}"); switch (result) { case HttpRequestParser.ParseResult.Incomplete: if (_input.Reading.IsCompleted) { // Didn't get the whole request and the connection ended throw new EndOfStreamException(); } // Need more data continue; case HttpRequestParser.ParseResult.Complete: // Done break; case HttpRequestParser.ParseResult.BadRequest: // TODO: Don't throw here; throw new Exception(); default: break; } } catch (Exception) { StatusCode = 400; await EndResponse(); return; } finally { _input.Advance(buffer.Start, buffer.End); } var context = _application.CreateContext(this); try { if (!_isHttp2 && RequestHeaders.ContainsKey("Upgrade") && TryUpgradeToHttp2()) { _outputFormatter.Write(_http2SwitchBytes); _isHttp2 = true; /* The first HTTP/2 frame sent by the server MUST be a server connection preface (Section 3.5) consisting of a SETTINGS frame (Section 6.5). */ _outputFormatter.Write(_emptySettingsFrame); await _outputFormatter.FlushAsync(); } await _application.ProcessRequestAsync(context); } catch (Exception ex) { StatusCode = 500; _application.DisposeContext(context, ex); } finally { await EndResponse(); } if (!KeepAlive) { break; } Reset(); } }