public async Task TakeMessageHeadersDoesNotCountAlreadyConsumedBytesTowardsSizeLimit() { const string startLine = "GET / HTTP/1.1\r\n"; // This doesn't actually need to be larger than the start line to cause the regression, // but doing so gives us a nice HeadersExceedMaxTotalSize error rather than an invalid slice // when we do see the regression. const string headerLine = "Header: makethislargerthanthestartline\r\n"; _serviceContext.ServerOptions.Limits.MaxRequestHeadersTotalSize = headerLine.Length; _http1Connection.Reset(); // Don't send header initially because the regression is only caught if TakeMessageHeaders // is called multiple times. The first call overcounted the header bytes consumed, and the // subsequent calls overslice the buffer due to the overcounting. await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"{startLine}")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; SequencePosition TakeStartLineAndMessageHeaders() { var reader = new SequenceReader <byte>(readableBuffer); Assert.True(_http1Connection.TakeStartLine(ref reader)); Assert.False(_http1Connection.TakeMessageHeaders(ref reader, trailers: false)); return(reader.Position); } _transport.Input.AdvanceTo(TakeStartLineAndMessageHeaders()); Assert.Equal(0, _http1Connection.RequestHeaders.Count); await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"{headerLine}\r\n")); readableBuffer = (await _transport.Input.ReadAsync()).Buffer; SequencePosition TakeMessageHeaders() { var reader = new SequenceReader <byte>(readableBuffer); Assert.True(_http1Connection.TakeMessageHeaders(ref reader, trailers: false)); return(reader.Position); } _transport.Input.AdvanceTo(TakeMessageHeaders()); Assert.Equal(1, _http1Connection.RequestHeaders.Count); Assert.Equal("makethislargerthanthestartline", _http1Connection.RequestHeaders["Header"]); }
public async Task TakeMessageHeadersThrowsWhenHeadersExceedTotalSizeLimit() { const string headerLine = "Header: value\r\n"; _serviceContext.ServerOptions.Limits.MaxRequestHeadersTotalSize = headerLine.Length - 1; _http1Connection.Reset(); await _application.Output.WriteAsync(Encoding.ASCII.GetBytes($"{headerLine}\r\n")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; var exception = Assert.Throws <BadHttpRequestException>(() => _http1Connection.TakeMessageHeaders(readableBuffer, out _consumed, out _examined)); _transport.Input.Advance(_consumed, _examined); Assert.Equal(CoreStrings.BadRequest_HeadersExceedMaxTotalSize, exception.Message); Assert.Equal(StatusCodes.Status431RequestHeaderFieldsTooLarge, exception.StatusCode); }
public async Task TakeMessageHeadersSucceedsWhenHeaderValueContainsUTF8() { var headerName = "Header"; var headerValueBytes = new byte[] { 0x46, 0x72, 0x61, 0x6e, 0xc3, 0xa7, 0x6f, 0x69, 0x73 }; var headerValue = Encoding.UTF8.GetString(headerValueBytes); _http1Connection.Reset(); await _application.Output.WriteAsync(Encoding.UTF8.GetBytes($"{headerName}: ")); await _application.Output.WriteAsync(headerValueBytes); await _application.Output.WriteAsync(Encoding.UTF8.GetBytes("\r\n\r\n")); var readableBuffer = (await _transport.Input.ReadAsync()).Buffer; _http1Connection.TakeMessageHeaders(readableBuffer, trailers: false, out _consumed, out _examined); _transport.Input.AdvanceTo(_consumed, _examined); Assert.Equal(headerValue, _http1Connection.RequestHeaders[headerName]); }