Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
{
internal partial class IISHttpContext : IFeatureCollection,
IHttpRequestFeature,
IHttpRequestBodyDetectionFeature,
IHttpResponseFeature,
IHttpResponseBodyFeature,
IHttpUpgradeFeature,
Expand Down Expand Up @@ -141,6 +142,8 @@ Stream IHttpRequestFeature.Body
set => RequestBody = value;
}

bool IHttpRequestBodyDetectionFeature.CanHaveBody => RequestCanHaveBody;

int IHttpResponseFeature.StatusCode
{
get => StatusCode;
Expand Down
16 changes: 16 additions & 0 deletions src/Servers/IIS/IIS/src/Core/IISHttpContext.Features.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace Microsoft.AspNetCore.Server.IIS.Core
internal partial class IISHttpContext
{
private static readonly Type IHttpRequestFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestFeature);
private static readonly Type IHttpRequestBodyDetectionFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestBodyDetectionFeature);
private static readonly Type IHttpResponseFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpResponseFeature);
private static readonly Type IHttpResponseBodyFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpResponseBodyFeature);
private static readonly Type IHttpRequestIdentifierFeatureType = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpRequestIdentifierFeature);
Expand All @@ -32,6 +33,7 @@ internal partial class IISHttpContext
private static readonly Type IHttpResetFeature = typeof(global::Microsoft.AspNetCore.Http.Features.IHttpResetFeature);

private object _currentIHttpRequestFeature;
private object _currentIHttpRequestBodyDetectionFeature;
private object _currentIHttpResponseFeature;
private object _currentIHttpResponseBodyFeature;
private object _currentIHttpRequestIdentifierFeature;
Expand All @@ -56,6 +58,7 @@ internal partial class IISHttpContext
private void Initialize()
{
_currentIHttpRequestFeature = this;
_currentIHttpRequestBodyDetectionFeature = this;
_currentIHttpResponseFeature = this;
_currentIHttpResponseBodyFeature = this;
_currentIHttpUpgradeFeature = this;
Expand All @@ -77,6 +80,10 @@ internal object FastFeatureGet(Type key)
{
return _currentIHttpRequestFeature;
}
if (key == IHttpRequestBodyDetectionFeature)
{
return _currentIHttpRequestBodyDetectionFeature;
}
if (key == IHttpResponseFeatureType)
{
return _currentIHttpResponseFeature;
Expand Down Expand Up @@ -174,6 +181,11 @@ internal void FastFeatureSet(Type key, object feature)
_currentIHttpRequestFeature = feature;
return;
}
if (key == IHttpRequestBodyDetectionFeature)
{
_currentIHttpRequestBodyDetectionFeature = feature;
return;
}
if (key == IHttpResponseFeatureType)
{
_currentIHttpResponseFeature = feature;
Expand Down Expand Up @@ -284,6 +296,10 @@ private IEnumerable<KeyValuePair<Type, object>> FastEnumerable()
{
yield return new KeyValuePair<Type, object>(IHttpRequestFeatureType, _currentIHttpRequestFeature as global::Microsoft.AspNetCore.Http.Features.IHttpRequestFeature);
}
if (_currentIHttpRequestBodyDetectionFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpRequestBodyDetectionFeature, _currentIHttpRequestBodyDetectionFeature as global::Microsoft.AspNetCore.Http.Features.IHttpRequestBodyDetectionFeature);
}
if (_currentIHttpResponseFeature != null)
{
yield return new KeyValuePair<Type, object>(IHttpResponseFeatureType, _currentIHttpResponseFeature as global::Microsoft.AspNetCore.Http.Features.IHttpResponseFeature);
Expand Down
17 changes: 17 additions & 0 deletions src/Servers/IIS/IIS/src/Core/IISHttpContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ internal unsafe IISHttpContext(
public string TraceIdentifier { get; set; }
public ClaimsPrincipal User { get; set; }
internal WindowsPrincipal WindowsUser { get; set; }
internal bool RequestCanHaveBody { get; private set; }
public Stream RequestBody { get; set; }
public Stream ResponseBody { get; set; }
public PipeWriter ResponsePipeWrapper { get; set; }
Expand Down Expand Up @@ -165,6 +166,8 @@ protected void InitializeContext()
RequestHeaders = new RequestHeaders(this);
HttpResponseHeaders = new HeaderCollection();
ResponseHeaders = HttpResponseHeaders;
// Request headers can be modified by the app, read these first.
RequestCanHaveBody = CheckRequestCanHaveBody();

if (_options.ForwardWindowsAuthentication)
{
Expand Down Expand Up @@ -250,6 +253,20 @@ public string ReasonPhrase

internal IISHttpServer Server => _server;

private bool CheckRequestCanHaveBody()
{
// Http/1.x requests with bodies require either a Content-Length or Transfer-Encoding header.
// Note Http.Sys adds the Transfer-Encoding: chunked header to HTTP/2 requests with bodies for back compat.
// Transfer-Encoding takes priority over Content-Length.
string transferEncoding = RequestHeaders[HttpKnownHeaderNames.TransferEncoding];
if (string.Equals("chunked", transferEncoding?.Trim(), StringComparison.OrdinalIgnoreCase))
{
return true;
}

return RequestHeaders.ContentLength.GetValueOrDefault() > 0;
}

private async Task InitializeResponse(bool flushHeaders)
{
await FireOnStarting();
Expand Down
Loading