#896 Have TestHost populate features before calling IHttpContextFactory.Create
This commit is contained in:
parent
af953b4883
commit
60c45c382b
|
|
@ -126,49 +126,51 @@ namespace Microsoft.AspNetCore.TestHost
|
||||||
}
|
}
|
||||||
|
|
||||||
var contextFeatures = new FeatureCollection();
|
var contextFeatures = new FeatureCollection();
|
||||||
contextFeatures.Set<IHttpRequestFeature>(new RequestFeature());
|
var requestFeature = new RequestFeature();
|
||||||
|
contextFeatures.Set<IHttpRequestFeature>(requestFeature);
|
||||||
_responseFeature = new ResponseFeature();
|
_responseFeature = new ResponseFeature();
|
||||||
contextFeatures.Set<IHttpResponseFeature>(_responseFeature);
|
contextFeatures.Set<IHttpResponseFeature>(_responseFeature);
|
||||||
Context = application.CreateContext(contextFeatures);
|
var requestLifetimeFeature = new HttpRequestLifetimeFeature();
|
||||||
var httpContext = Context.HttpContext;
|
contextFeatures.Set<IHttpRequestLifetimeFeature>(requestLifetimeFeature);
|
||||||
|
|
||||||
var serverRequest = httpContext.Request;
|
requestFeature.Protocol = "HTTP/" + request.Version.ToString(fieldCount: 2);
|
||||||
serverRequest.Protocol = "HTTP/" + request.Version.ToString(2);
|
requestFeature.Scheme = request.RequestUri.Scheme;
|
||||||
serverRequest.Scheme = request.RequestUri.Scheme;
|
requestFeature.Method = request.Method.ToString();
|
||||||
serverRequest.Method = request.Method.ToString();
|
|
||||||
|
|
||||||
var fullPath = PathString.FromUriComponent(request.RequestUri);
|
var fullPath = PathString.FromUriComponent(request.RequestUri);
|
||||||
PathString remainder;
|
PathString remainder;
|
||||||
if (fullPath.StartsWithSegments(pathBase, out remainder))
|
if (fullPath.StartsWithSegments(pathBase, out remainder))
|
||||||
{
|
{
|
||||||
serverRequest.PathBase = pathBase;
|
requestFeature.PathBase = pathBase.Value;
|
||||||
serverRequest.Path = remainder;
|
requestFeature.Path = remainder.Value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serverRequest.PathBase = PathString.Empty;
|
requestFeature.PathBase = string.Empty;
|
||||||
serverRequest.Path = fullPath;
|
requestFeature.Path = fullPath.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
serverRequest.QueryString = QueryString.FromUriComponent(request.RequestUri);
|
requestFeature.QueryString = QueryString.FromUriComponent(request.RequestUri).Value;
|
||||||
|
|
||||||
foreach (var header in request.Headers)
|
foreach (var header in request.Headers)
|
||||||
{
|
{
|
||||||
serverRequest.Headers.Append(header.Key, header.Value.ToArray());
|
requestFeature.Headers.Append(header.Key, header.Value.ToArray());
|
||||||
}
|
}
|
||||||
var requestContent = request.Content;
|
var requestContent = request.Content;
|
||||||
if (requestContent != null)
|
if (requestContent != null)
|
||||||
{
|
{
|
||||||
foreach (var header in request.Content.Headers)
|
foreach (var header in request.Content.Headers)
|
||||||
{
|
{
|
||||||
serverRequest.Headers.Append(header.Key, header.Value.ToArray());
|
requestFeature.Headers.Append(header.Key, header.Value.ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_responseStream = new ResponseStream(ReturnResponseMessageAsync, AbortRequest);
|
_responseStream = new ResponseStream(ReturnResponseMessageAsync, AbortRequest);
|
||||||
httpContext.Response.Body = _responseStream;
|
_responseFeature.Body = _responseStream;
|
||||||
httpContext.Response.StatusCode = 200;
|
_responseFeature.StatusCode = 200;
|
||||||
httpContext.RequestAborted = _requestAbortedSource.Token;
|
requestLifetimeFeature.RequestAborted = _requestAbortedSource.Token;
|
||||||
|
|
||||||
|
Context = application.CreateContext(contextFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Context Context { get; private set; }
|
public Context Context { get; private set; }
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,31 @@ namespace Microsoft.AspNetCore.TestHost
|
||||||
return httpClient.GetAsync("https://example.com/A/Path/and/file.txt?and=query");
|
return httpClient.GetAsync("https://example.com/A/Path/and/file.txt?and=query");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public Task ExpectedKeysAreInFeatures()
|
||||||
|
{
|
||||||
|
var handler = new ClientHandler(new PathString("/A/Path/"), new InspectingApplication(features =>
|
||||||
|
{
|
||||||
|
// TODO: Assert.True(context.RequestAborted.CanBeCanceled);
|
||||||
|
Assert.Equal("HTTP/1.1", features.Get<IHttpRequestFeature>().Protocol);
|
||||||
|
Assert.Equal("GET", features.Get<IHttpRequestFeature>().Method);
|
||||||
|
Assert.Equal("https", features.Get<IHttpRequestFeature>().Scheme);
|
||||||
|
Assert.Equal("/A/Path", features.Get<IHttpRequestFeature>().PathBase);
|
||||||
|
Assert.Equal("/and/file.txt", features.Get<IHttpRequestFeature>().Path);
|
||||||
|
Assert.Equal("?and=query", features.Get<IHttpRequestFeature>().QueryString);
|
||||||
|
Assert.NotNull(features.Get<IHttpRequestFeature>().Body);
|
||||||
|
Assert.NotNull(features.Get<IHttpRequestFeature>().Headers);
|
||||||
|
Assert.NotNull(features.Get<IHttpResponseFeature>().Headers);
|
||||||
|
Assert.NotNull(features.Get<IHttpResponseFeature>().Body);
|
||||||
|
Assert.Equal(200, features.Get<IHttpResponseFeature>().StatusCode);
|
||||||
|
Assert.Null(features.Get<IHttpResponseFeature>().ReasonPhrase);
|
||||||
|
Assert.Equal("example.com", features.Get<IHttpRequestFeature>().Headers["host"]);
|
||||||
|
Assert.NotNull(features.Get<IHttpRequestLifetimeFeature>());
|
||||||
|
}));
|
||||||
|
var httpClient = new HttpClient(handler);
|
||||||
|
return httpClient.GetAsync("https://example.com/A/Path/and/file.txt?and=query");
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public Task SingleSlashNotMovedToPathBase()
|
public Task SingleSlashNotMovedToPathBase()
|
||||||
{
|
{
|
||||||
|
|
@ -274,6 +299,35 @@ namespace Microsoft.AspNetCore.TestHost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class InspectingApplication : IHttpApplication<Context>
|
||||||
|
{
|
||||||
|
Action<IFeatureCollection> _inspector;
|
||||||
|
|
||||||
|
public InspectingApplication(Action<IFeatureCollection> inspector)
|
||||||
|
{
|
||||||
|
_inspector = inspector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Context CreateContext(IFeatureCollection contextFeatures)
|
||||||
|
{
|
||||||
|
_inspector(contextFeatures);
|
||||||
|
return new Context()
|
||||||
|
{
|
||||||
|
HttpContext = new DefaultHttpContext(contextFeatures)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DisposeContext(Context context, Exception exception)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ProcessRequestAsync(Context context)
|
||||||
|
{
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[ConditionalFact]
|
[ConditionalFact]
|
||||||
[FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Hangs randomly (issue #507)")]
|
[FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Hangs randomly (issue #507)")]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue