Make the IHttpParser per frame and add a reset (#1415)
* Make the IHttpParser per frame and add a reset - Made the IHttpParser a per frame object so state can be stored across method calls and parses. - Added HttpParserFactory to ServiceContext
This commit is contained in:
parent
d3694f085a
commit
cb6059c143
|
|
@ -86,7 +86,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
ServerOptions = context.ListenerContext.ServiceContext.ServerOptions;
|
||||
|
||||
_pathBase = context.ListenerContext.ListenOptions.PathBase;
|
||||
_parser = context.ListenerContext.ServiceContext.HttpParser;
|
||||
_parser = context.ListenerContext.ServiceContext.HttpParserFactory(this);
|
||||
|
||||
FrameControl = this;
|
||||
_keepAliveMilliseconds = (long)ServerOptions.Limits.KeepAliveTimeout.TotalMilliseconds;
|
||||
|
|
@ -379,6 +379,9 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
_requestHeadersParsed = 0;
|
||||
|
||||
_responseBytesWritten = 0;
|
||||
|
||||
// When testing parser can be null
|
||||
_parser.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -10,5 +10,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
bool ParseRequestLine<T>(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) where T : IHttpRequestLineHandler;
|
||||
|
||||
bool ParseHeaders<T>(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) where T : IHttpHeadersHandler;
|
||||
|
||||
void Reset();
|
||||
}
|
||||
}
|
||||
|
|
@ -525,6 +525,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal.Http
|
|||
Log.IsEnabled(LogLevel.Information) ? span.GetAsciiStringEscaped(MaxRequestLineError) : string.Empty);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private enum HeaderState
|
||||
{
|
||||
Name,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Internal
|
|||
|
||||
public IThreadPool ThreadPool { get; set; }
|
||||
|
||||
public IHttpParser HttpParser { get; set; }
|
||||
public Func<Frame, IHttpParser> HttpParserFactory { get; set; }
|
||||
|
||||
public Func<ConnectionContext, Frame> FrameFactory { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel
|
|||
},
|
||||
AppLifetime = _applicationLifetime,
|
||||
Log = trace,
|
||||
HttpParser = new KestrelHttpParser(trace),
|
||||
HttpParserFactory = frame => new KestrelHttpParser(frame.ConnectionContext.ListenerContext.ServiceContext.Log),
|
||||
ThreadPool = threadPool,
|
||||
DateHeaderValueManager = dateHeaderValueManager,
|
||||
ServerOptions = Options
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
}
|
||||
Pipe.Reader.Advance(consumed, examined);
|
||||
}
|
||||
while(true);
|
||||
while (true);
|
||||
}
|
||||
|
||||
private void ThrowInvalidStartLine()
|
||||
|
|
@ -179,7 +179,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Performance
|
|||
public void Setup()
|
||||
{
|
||||
var connectionContext = new MockConnection(new KestrelServerOptions());
|
||||
connectionContext.ListenerContext.ServiceContext.HttpParser = (IHttpParser) Activator.CreateInstance(ParserType, connectionContext.ListenerContext.ServiceContext.Log);
|
||||
connectionContext.ListenerContext.ServiceContext.HttpParserFactory = frame => (IHttpParser)Activator.CreateInstance(ParserType, frame.ConnectionContext.ListenerContext.ServiceContext.Log);
|
||||
|
||||
Frame = new Frame<object>(application: null, context: connectionContext);
|
||||
PipelineFactory = new PipeFactory();
|
||||
|
|
|
|||
|
|
@ -4,16 +4,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO.Pipelines;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Internal;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.Http;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Internal.Infrastructure;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Xunit;
|
||||
using Microsoft.Net.Http.Headers;
|
||||
|
||||
namespace Microsoft.AspNetCore.Server.KestrelTests
|
||||
{
|
||||
|
|
@ -27,7 +25,8 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
var serviceContext = new ServiceContext
|
||||
{
|
||||
DateHeaderValueManager = new DateHeaderValueManager(),
|
||||
ServerOptions = serverOptions
|
||||
ServerOptions = serverOptions,
|
||||
HttpParserFactory = f => new NoopHttpParser(),
|
||||
};
|
||||
var listenerContext = new ListenerContext(serviceContext)
|
||||
{
|
||||
|
|
@ -268,5 +267,28 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
"42,000",
|
||||
"42.000",
|
||||
};
|
||||
|
||||
private class NoopHttpParser : IHttpParser
|
||||
{
|
||||
public bool ParseHeaders<T>(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined, out int consumedBytes) where T : IHttpHeadersHandler
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.End;
|
||||
consumedBytes = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool ParseRequestLine<T>(T handler, ReadableBuffer buffer, out ReadCursor consumed, out ReadCursor examined) where T : IHttpRequestLineHandler
|
||||
{
|
||||
consumed = buffer.Start;
|
||||
examined = buffer.End;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
{
|
||||
DateHeaderValueManager = new DateHeaderValueManager(),
|
||||
ServerOptions = new KestrelServerOptions(),
|
||||
HttpParser = new KestrelHttpParser(trace),
|
||||
HttpParserFactory = frame => new KestrelHttpParser(trace),
|
||||
Log = trace
|
||||
};
|
||||
var listenerContext = new ListenerContext(_serviceContext)
|
||||
|
|
@ -484,7 +484,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
await _socketInput.Writer.WriteAsync(requestLineBytes);
|
||||
|
||||
var readableBuffer = (await _socketInput.Reader.ReadAsync()).Buffer;
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() =>_frame.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
var exception = Assert.Throws<BadHttpRequestException>(() => _frame.TakeStartLine(readableBuffer, out _consumed, out _examined));
|
||||
_socketInput.Reader.Advance(_consumed, _examined);
|
||||
|
||||
Assert.Equal("Request line too long.", exception.Message);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
DateHeaderValueManager = serviceContextPrimary.DateHeaderValueManager,
|
||||
ServerOptions = serviceContextPrimary.ServerOptions,
|
||||
ThreadPool = serviceContextPrimary.ThreadPool,
|
||||
HttpParser = new KestrelHttpParser(serviceContextPrimary.Log),
|
||||
HttpParserFactory = frame => new KestrelHttpParser(serviceContextPrimary.Log),
|
||||
FrameFactory = context =>
|
||||
{
|
||||
return new Frame<DefaultHttpContext>(new TestApplication(c =>
|
||||
|
|
@ -122,7 +122,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
DateHeaderValueManager = serviceContextPrimary.DateHeaderValueManager,
|
||||
ServerOptions = serviceContextPrimary.ServerOptions,
|
||||
ThreadPool = serviceContextPrimary.ThreadPool,
|
||||
HttpParser = new KestrelHttpParser(serviceContextPrimary.Log),
|
||||
HttpParserFactory = frame => new KestrelHttpParser(serviceContextPrimary.Log),
|
||||
FrameFactory = context =>
|
||||
{
|
||||
return new Frame<DefaultHttpContext>(new TestApplication(c =>
|
||||
|
|
@ -245,7 +245,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
DateHeaderValueManager = serviceContextPrimary.DateHeaderValueManager,
|
||||
ServerOptions = serviceContextPrimary.ServerOptions,
|
||||
ThreadPool = serviceContextPrimary.ThreadPool,
|
||||
HttpParser = new KestrelHttpParser(serviceContextPrimary.Log),
|
||||
HttpParserFactory = frame => new KestrelHttpParser(serviceContextPrimary.Log),
|
||||
FrameFactory = context =>
|
||||
{
|
||||
return new Frame<DefaultHttpContext>(new TestApplication(c =>
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
{
|
||||
DateHeaderValueManager = new DateHeaderValueManager(),
|
||||
ServerOptions = new KestrelServerOptions(),
|
||||
HttpParser = new KestrelHttpParser(trace),
|
||||
HttpParserFactory = frame => new KestrelHttpParser(trace),
|
||||
};
|
||||
var listenerContext = new ListenerContext(serviceContext)
|
||||
{
|
||||
|
|
@ -45,7 +45,7 @@ namespace Microsoft.AspNetCore.Server.KestrelTests
|
|||
|
||||
_memoryPool = new MemoryPool();
|
||||
_pipelineFactory = new PipeFactory();
|
||||
FrameContext.Input = _pipelineFactory.Create();;
|
||||
FrameContext.Input = _pipelineFactory.Create(); ;
|
||||
}
|
||||
|
||||
public Frame FrameContext { get; set; }
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Testing
|
|||
ThreadPool = new LoggingThreadPool(Log);
|
||||
DateHeaderValueManager = new DateHeaderValueManager(systemClock: new MockSystemClock());
|
||||
DateHeaderValue = DateHeaderValueManager.GetDateHeaderValues().String;
|
||||
HttpParser = new KestrelHttpParser(Log);
|
||||
HttpParserFactory = frame => new KestrelHttpParser(Log);
|
||||
ServerOptions = new KestrelServerOptions
|
||||
{
|
||||
AddServerHeader = false,
|
||||
|
|
|
|||
Loading…
Reference in New Issue