Родитель
748a6e1090
Коммит
2681e8b3d1
|
@ -29,6 +29,9 @@ namespace Microsoft.Net.Http.Server
|
|||
{
|
||||
internal const string HttpScheme = "http";
|
||||
internal const string HttpsScheme = "https";
|
||||
internal const string Chunked = "chunked";
|
||||
internal const string Close = "close";
|
||||
internal const string Zero = "0";
|
||||
internal const string SchemeDelimiter = "://";
|
||||
|
||||
internal static Version V1_0 = new Version(1, 0);
|
||||
|
|
|
@ -28,6 +28,8 @@ namespace Microsoft.Net.Http.Server
|
|||
None = 0,
|
||||
Chunked = 1, // Transfer-Encoding: chunked
|
||||
ContentLength = 2, // Content-Length: XXX
|
||||
Invalid = 3,
|
||||
Close = 3, // Connection: close
|
||||
PassThrough = 4, // The application is handling the boundary themselves (e.g. chunking themselves).
|
||||
Invalid = 5,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -263,6 +263,11 @@ namespace Microsoft.Net.Http.Server
|
|||
get { return _httpMethod; }
|
||||
}
|
||||
|
||||
public bool IsHeadMethod
|
||||
{
|
||||
get { return string.Equals(_httpMethod, "HEAD", StringComparison.OrdinalIgnoreCase); }
|
||||
}
|
||||
|
||||
public Stream Body
|
||||
{
|
||||
get
|
||||
|
@ -413,7 +418,7 @@ namespace Microsoft.Net.Http.Server
|
|||
{
|
||||
get
|
||||
{
|
||||
return Headers.Get(HttpKnownHeaderNames.ContentLength);
|
||||
return Headers.Get(HttpKnownHeaderNames.ContentType);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,13 +38,13 @@ namespace Microsoft.Net.Http.Server
|
|||
{
|
||||
public sealed unsafe class Response
|
||||
{
|
||||
private static readonly string[] ZeroContentLength = new[] { "0" };
|
||||
private static readonly string[] ZeroContentLength = new[] { Constants.Zero };
|
||||
|
||||
private ResponseState _responseState;
|
||||
private HeaderCollection _headers;
|
||||
private string _reasonPhrase;
|
||||
private ResponseStream _nativeStream;
|
||||
private long _contentLength;
|
||||
private long _expectedBodyLength;
|
||||
private BoundaryType _boundaryType;
|
||||
private UnsafeNclNativeMethods.HttpApi.HTTP_RESPONSE_V2 _nativeResponse;
|
||||
private IList<Tuple<Action<object>, object>> _onSendingHeadersActions;
|
||||
|
@ -166,11 +166,11 @@ namespace Microsoft.Net.Http.Server
|
|||
get { return _headers; }
|
||||
}
|
||||
|
||||
internal long CalculatedLength
|
||||
internal long ExpectedBodyLength
|
||||
{
|
||||
get
|
||||
{
|
||||
return _contentLength;
|
||||
return _expectedBodyLength;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ namespace Microsoft.Net.Http.Server
|
|||
if (!string.IsNullOrWhiteSpace(contentLengthString))
|
||||
{
|
||||
contentLengthString = contentLengthString.Trim();
|
||||
if (string.Equals("0", contentLengthString, StringComparison.Ordinal))
|
||||
if (string.Equals(Constants.Zero, contentLengthString, StringComparison.Ordinal))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -225,7 +225,7 @@ namespace Microsoft.Net.Http.Server
|
|||
{
|
||||
get
|
||||
{
|
||||
return Headers.Get(HttpKnownHeaderNames.ContentLength);
|
||||
return Headers.Get(HttpKnownHeaderNames.ContentType);
|
||||
}
|
||||
set
|
||||
{
|
||||
|
@ -241,44 +241,6 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
}
|
||||
|
||||
private Version GetProtocolVersion()
|
||||
{
|
||||
/*
|
||||
Version requestVersion = Request.ProtocolVersion;
|
||||
Version responseVersion = requestVersion;
|
||||
string protocolVersion = RequestContext.Environment.Get<string>(Constants.HttpResponseProtocolKey);
|
||||
|
||||
// Optional
|
||||
if (!string.IsNullOrWhiteSpace(protocolVersion))
|
||||
{
|
||||
if (string.Equals("HTTP/1.1", protocolVersion, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
responseVersion = Constants.V1_1;
|
||||
}
|
||||
if (string.Equals("HTTP/1.0", protocolVersion, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
responseVersion = Constants.V1_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Just log? It's too late to get this to user code.
|
||||
throw new ArgumentException(string.Empty, Constants.HttpResponseProtocolKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (requestVersion == responseVersion)
|
||||
{
|
||||
return requestVersion;
|
||||
}
|
||||
|
||||
// Return the lesser of the two versions. There are only two, so it it will always be 1.0.
|
||||
return Constants.V1_0;*/
|
||||
|
||||
// TODO: IHttpResponseInformation does not define a response protocol version. Http.Sys doesn't let
|
||||
// us send anything but 1.1 anyways, but we could at least use it to set things like the connection header.
|
||||
return Request.ProtocolVersion;
|
||||
}
|
||||
|
||||
// should only be called from RequestContext
|
||||
internal void Dispose()
|
||||
{
|
||||
|
@ -476,121 +438,87 @@ namespace Microsoft.Net.Http.Server
|
|||
RequestContext.Server.AuthenticationManager.SetAuthenticationChallenge(RequestContext);
|
||||
}
|
||||
|
||||
UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
|
||||
var flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
|
||||
Debug.Assert(!ComputedHeaders, "HttpListenerResponse::ComputeHeaders()|ComputedHeaders is true.");
|
||||
_responseState = ResponseState.ComputedHeaders;
|
||||
/*
|
||||
// here we would check for BoundaryType.Raw, in this case we wouldn't need to do anything
|
||||
if (m_BoundaryType==BoundaryType.Raw) {
|
||||
return flags;
|
||||
}
|
||||
*/
|
||||
|
||||
// Check the response headers to determine the correct keep alive and boundary type.
|
||||
Version responseVersion = GetProtocolVersion();
|
||||
_nativeResponse.Response_V1.Version.MajorVersion = (ushort)responseVersion.Major;
|
||||
_nativeResponse.Response_V1.Version.MinorVersion = (ushort)responseVersion.Minor;
|
||||
bool keepAlive = responseVersion >= Constants.V1_1;
|
||||
string connectionString = Headers.Get(HttpKnownHeaderNames.Connection);
|
||||
string keepAliveString = Headers.Get(HttpKnownHeaderNames.KeepAlive);
|
||||
bool closeSet = false;
|
||||
bool keepAliveSet = false;
|
||||
// Gather everything from the request that affects the response:
|
||||
var requestVersion = Request.ProtocolVersion;
|
||||
var requestConnectionString = Request.Headers.Get(HttpKnownHeaderNames.Connection);
|
||||
var isHeadRequest = Request.IsHeadMethod;
|
||||
var requestCloseSet = Matches(Constants.Close, requestConnectionString);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(connectionString) && string.Equals("close", connectionString.Trim(), StringComparison.OrdinalIgnoreCase))
|
||||
// Gather everything the app may have set on the response:
|
||||
// Http.Sys does not allow us to specify the response protocol version, assume this is a HTTP/1.1 response when making decisions.
|
||||
var responseConnectionString = Headers.Get(HttpKnownHeaderNames.Connection);
|
||||
var transferEncodingString = Headers.Get(HttpKnownHeaderNames.TransferEncoding);
|
||||
var responseContentLength = ContentLength;
|
||||
var responseCloseSet = Matches(Constants.Close, responseConnectionString);
|
||||
var responseChunkedSet = Matches(Constants.Chunked, transferEncodingString);
|
||||
var statusCanHaveBody = CanSendResponseBody(_requestContext.Response.StatusCode);
|
||||
|
||||
// Determine if the connection will be kept alive or closed.
|
||||
var keepConnectionAlive = true;
|
||||
if (requestVersion <= Constants.V1_0 // Http.Sys does not support "Keep-Alive: true" or "Connection: Keep-Alive"
|
||||
|| (requestVersion == Constants.V1_1 && requestCloseSet)
|
||||
|| responseCloseSet)
|
||||
{
|
||||
keepAlive = false;
|
||||
closeSet = true;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(keepAliveString) && string.Equals("true", keepAliveString.Trim(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
keepAlive = true;
|
||||
keepAliveSet = true;
|
||||
keepConnectionAlive = false;
|
||||
}
|
||||
|
||||
// Content-Length takes priority
|
||||
long? contentLength = ContentLength;
|
||||
string transferEncodingString = Headers.Get(HttpKnownHeaderNames.TransferEncoding);
|
||||
|
||||
if (responseVersion == Constants.V1_0 && !string.IsNullOrEmpty(transferEncodingString)
|
||||
&& string.Equals("chunked", transferEncodingString.Trim(), StringComparison.OrdinalIgnoreCase))
|
||||
// Determine the body format. If the user asks to do something, let them, otherwise choose a good default for the scenario.
|
||||
if (responseContentLength.HasValue)
|
||||
{
|
||||
// A 1.0 client can't process chunked responses.
|
||||
Headers.Remove(HttpKnownHeaderNames.TransferEncoding);
|
||||
transferEncodingString = null;
|
||||
}
|
||||
|
||||
if (contentLength.HasValue)
|
||||
{
|
||||
_contentLength = contentLength.Value;
|
||||
_boundaryType = BoundaryType.ContentLength;
|
||||
if (_contentLength == 0)
|
||||
{
|
||||
flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
|
||||
}
|
||||
// ComputeLeftToWrite checks for HEAD requests when setting _leftToWrite
|
||||
_expectedBodyLength = responseContentLength.Value;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(transferEncodingString)
|
||||
&& string.Equals("chunked", transferEncodingString.Trim(), StringComparison.OrdinalIgnoreCase))
|
||||
else if (responseChunkedSet)
|
||||
{
|
||||
// The application is performing it's own chunking.
|
||||
_boundaryType = BoundaryType.PassThrough;
|
||||
}
|
||||
else if (endOfRequest && !(isHeadRequest && statusCanHaveBody)) // HEAD requests always end without a body. Assume a GET response would have a body.
|
||||
{
|
||||
if (statusCanHaveBody)
|
||||
{
|
||||
Headers[HttpKnownHeaderNames.ContentLength] = Constants.Zero;
|
||||
}
|
||||
_boundaryType = BoundaryType.ContentLength;
|
||||
_expectedBodyLength = 0;
|
||||
}
|
||||
else if (keepConnectionAlive && requestVersion == Constants.V1_1)
|
||||
{
|
||||
// Then Transfer-Encoding: chunked
|
||||
_boundaryType = BoundaryType.Chunked;
|
||||
}
|
||||
else if (endOfRequest)
|
||||
{
|
||||
// The request is ending without a body, add a Content-Length: 0 header.
|
||||
Headers[HttpKnownHeaderNames.ContentLength] = "0";
|
||||
_boundaryType = BoundaryType.ContentLength;
|
||||
_contentLength = 0;
|
||||
flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE;
|
||||
Headers[HttpKnownHeaderNames.TransferEncoding] = Constants.Chunked;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Then fall back to Connection:Close transparent mode.
|
||||
_boundaryType = BoundaryType.None;
|
||||
flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE; // seems like HTTP_SEND_RESPONSE_FLAG_MORE_DATA but this hangs the app;
|
||||
if (responseVersion == Constants.V1_0)
|
||||
{
|
||||
keepAlive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Headers[HttpKnownHeaderNames.TransferEncoding] = "chunked";
|
||||
_boundaryType = BoundaryType.Chunked;
|
||||
}
|
||||
|
||||
if (CanSendResponseBody(_requestContext.Response.StatusCode))
|
||||
{
|
||||
_contentLength = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Headers[HttpKnownHeaderNames.ContentLength] = "0";
|
||||
_contentLength = 0;
|
||||
_boundaryType = BoundaryType.ContentLength;
|
||||
}
|
||||
// The length cannot be determined, so we must close the connection
|
||||
keepConnectionAlive = false;
|
||||
_boundaryType = BoundaryType.Close;
|
||||
}
|
||||
|
||||
// Also, Keep-Alive vs Connection Close
|
||||
if (!keepAlive)
|
||||
// Managed connection lifetime
|
||||
if (!keepConnectionAlive)
|
||||
{
|
||||
if (!closeSet)
|
||||
// All Http.Sys responses are v1.1, so use 1.1 response headers
|
||||
// Note that if we don't add this header, Http.Sys will often do it for us.
|
||||
if (!responseCloseSet)
|
||||
{
|
||||
Headers.Append(HttpKnownHeaderNames.Connection, "close");
|
||||
}
|
||||
if (flags == UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.NONE)
|
||||
{
|
||||
flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Request.ProtocolVersion.Minor == 0 && !keepAliveSet)
|
||||
{
|
||||
Headers[HttpKnownHeaderNames.KeepAlive] = "true";
|
||||
Headers.Append(HttpKnownHeaderNames.Connection, Constants.Close);
|
||||
}
|
||||
flags = UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private static bool Matches(string knownValue, string input)
|
||||
{
|
||||
return string.Equals(knownValue, input?.Trim(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private List<GCHandle> SerializeHeaders(bool isOpaqueUpgrade)
|
||||
{
|
||||
Headers.Sent = true; // Prohibit further modifications.
|
||||
|
|
|
@ -231,7 +231,7 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
else if (_requestContext.Response.BoundaryType == BoundaryType.ContentLength)
|
||||
{
|
||||
_leftToWrite = _requestContext.Response.CalculatedLength;
|
||||
_leftToWrite = _requestContext.Response.ExpectedBodyLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -764,7 +764,7 @@ namespace Microsoft.Net.Http.Server
|
|||
if (_leftToWrite > 0 && !_inOpaqueMode)
|
||||
{
|
||||
_requestContext.Abort();
|
||||
// TODO: Reduce this to a logged warning, it is thrown too late to be visible in user code.
|
||||
// This is logged rather than thrown because it is too late for an exception to be visible in user code.
|
||||
LogHelper.LogError(_requestContext.Logger, "ResponseStream::Dispose", "Fewer bytes were written than were specified in the Content-Length.");
|
||||
return;
|
||||
}
|
||||
|
@ -775,9 +775,12 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
|
||||
uint statusCode = 0;
|
||||
if ((_requestContext.Response.BoundaryType == BoundaryType.Chunked || _requestContext.Response.BoundaryType == BoundaryType.None) && (String.Compare(_requestContext.Request.Method, "HEAD", StringComparison.OrdinalIgnoreCase) != 0))
|
||||
if ((_requestContext.Response.BoundaryType == BoundaryType.Chunked
|
||||
|| _requestContext.Response.BoundaryType == BoundaryType.Close
|
||||
|| _requestContext.Response.BoundaryType == BoundaryType.PassThrough)
|
||||
&& !_requestContext.Request.IsHeadMethod)
|
||||
{
|
||||
if (_requestContext.Response.BoundaryType == BoundaryType.None)
|
||||
if (_requestContext.Response.BoundaryType == BoundaryType.Close)
|
||||
{
|
||||
flags |= UnsafeNclNativeMethods.HttpApi.HTTP_FLAGS.HTTP_SEND_RESPONSE_FLAG_DISCONNECT;
|
||||
}
|
||||
|
|
|
@ -99,28 +99,7 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
Assert.Equal(new byte[30], await response.Content.ReadAsByteArrayAsync());
|
||||
}
|
||||
}
|
||||
/* TODO: response protocol
|
||||
[Fact]
|
||||
public async Task ResponseBody_Http10WriteNoHeaders_DefaultsConnectionClose()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
{
|
||||
env["owin.ResponseProtocol"] = "HTTP/1.0";
|
||||
env.Get<Stream>("owin.ResponseBody").Write(new byte[10], 0, 10);
|
||||
return env.Get<Stream>("owin.ResponseBody").WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
HttpResponseMessage response = await SendRequestAsync(address);
|
||||
Assert.Equal(200, (int)response.StatusCode);
|
||||
Assert.Equal(new Version(1, 1), response.Version); // Http.Sys won't transmit 1.0
|
||||
IEnumerable<string> ignored;
|
||||
Assert.False(response.Content.Headers.TryGetValues("content-length", out ignored), "Content-Length");
|
||||
Assert.Null(response.Headers.TransferEncodingChunked);
|
||||
Assert.Equal(new byte[20], await response.Content.ReadAsByteArrayAsync());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseBody_WriteContentLengthNoneWritten_Throws()
|
||||
{
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
// permissions and limitations under the License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
|
@ -134,6 +136,7 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
var responseInfo = httpContext.GetFeature<IHttpResponseFeature>();
|
||||
var responseHeaders = responseInfo.Headers;
|
||||
responseHeaders["Connection"] = new string[] { "Close" };
|
||||
httpContext.Response.Body.Flush(); // Http.Sys adds the Content-Length: header for us if we don't flush
|
||||
return Task.FromResult(0);
|
||||
}))
|
||||
{
|
||||
|
@ -141,47 +144,12 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
response.EnsureSuccessStatusCode();
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
}
|
||||
}
|
||||
/* TODO:
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_SendsHttp10_Gets11Close()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
{
|
||||
env["owin.ResponseProtocol"] = "HTTP/1.0";
|
||||
return Task.FromResult(0);
|
||||
}))
|
||||
{
|
||||
HttpResponseMessage response = await SendRequestAsync(address);
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_SendsHttp10WithBody_Gets11Close()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
{
|
||||
env["owin.ResponseProtocol"] = "HTTP/1.0";
|
||||
return env.Get<Stream>("owin.ResponseBody").WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
HttpResponseMessage response = await SendRequestAsync(address);
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.False(response.Content.Headers.Contains("Content-Length"));
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
IEnumerable<string> values;
|
||||
var result = response.Content.Headers.TryGetValues("Content-Length", out values);
|
||||
Assert.False(result);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_HTTP10Request_Gets11Close()
|
||||
|
@ -201,12 +169,13 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_HTTP10Request_RemovesChunkedHeader()
|
||||
public async Task ResponseHeaders_HTTP10RequestWithChunkedHeader_ManualChunking()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
|
@ -215,7 +184,8 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
var responseInfo = httpContext.GetFeature<IHttpResponseFeature>();
|
||||
var responseHeaders = responseInfo.Headers;
|
||||
responseHeaders["Transfer-Encoding"] = new string[] { "chunked" };
|
||||
return responseInfo.Body.WriteAsync(new byte[10], 0, 10);
|
||||
var responseBytes = Encoding.ASCII.GetBytes("10\r\nManually Chunked\r\n0\r\n\r\n");
|
||||
return responseInfo.Body.WriteAsync(responseBytes, 0, responseBytes.Length);
|
||||
}))
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
|
@ -225,10 +195,11 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
HttpResponseMessage response = await client.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.True(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.False(response.Content.Headers.Contains("Content-Length"));
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
Assert.Equal("Manually Chunked", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,14 +162,13 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_Chunked_Chunked()
|
||||
public async Task ResponseSendFile_Unspecified_Chunked()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
{
|
||||
var httpContext = new DefaultHttpContext((IFeatureCollection)env);
|
||||
var sendFile = httpContext.GetFeature<IHttpSendFileFeature>();
|
||||
httpContext.Response.Headers["Transfer-EncodinG"] = "CHUNKED";
|
||||
return sendFile.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
|
||||
}))
|
||||
{
|
||||
|
@ -183,14 +182,13 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_MultipleChunks_Chunked()
|
||||
public async Task ResponseSendFile_MultipleWrites_Chunked()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
{
|
||||
var httpContext = new DefaultHttpContext((IFeatureCollection)env);
|
||||
var sendFile = httpContext.GetFeature<IHttpSendFileFeature>();
|
||||
httpContext.Response.Headers["Transfer-EncodinG"] = "CHUNKED";
|
||||
sendFile.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None).Wait();
|
||||
return sendFile.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
|
||||
}))
|
||||
|
@ -205,7 +203,7 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_ChunkedHalfOfFile_Chunked()
|
||||
public async Task ResponseSendFile_HalfOfFile_Chunked()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
|
@ -225,7 +223,7 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_ChunkedOffsetOutOfRange_Throws()
|
||||
public async Task ResponseSendFile_OffsetOutOfRange_Throws()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
|
@ -241,7 +239,7 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_ChunkedCountOutOfRange_Throws()
|
||||
public async Task ResponseSendFile_CountOutOfRange_Throws()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
|
@ -257,7 +255,7 @@ namespace Microsoft.AspNet.Server.WebListener
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_ChunkedCount0_Chunked()
|
||||
public async Task ResponseSendFile_Count0_Chunked()
|
||||
{
|
||||
string address;
|
||||
using (Utilities.CreateHttpServer(out address, env =>
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
@ -37,7 +38,7 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseBody_WriteChunked_Chunked()
|
||||
public async Task ResponseBody_WriteChunked_ManuallyChunked()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
@ -45,11 +46,10 @@ namespace Microsoft.Net.Http.Server
|
|||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Request.Headers["transfeR-Encoding"] = " CHunked ";
|
||||
context.Response.Headers["transfeR-Encoding"] = " CHunked ";
|
||||
Stream stream = context.Response.Body;
|
||||
stream.EndWrite(stream.BeginWrite(new byte[10], 0, 10, null, null));
|
||||
stream.Write(new byte[10], 0, 10);
|
||||
await stream.WriteAsync(new byte[10], 0, 10);
|
||||
var responseBytes = Encoding.ASCII.GetBytes("10\r\nManually Chunked\r\n0\r\n\r\n");
|
||||
await stream.WriteAsync(responseBytes, 0, responseBytes.Length);
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
|
@ -58,7 +58,7 @@ namespace Microsoft.Net.Http.Server
|
|||
IEnumerable<string> ignored;
|
||||
Assert.False(response.Content.Headers.TryGetValues("content-length", out ignored), "Content-Length");
|
||||
Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked");
|
||||
Assert.Equal(new byte[30], await response.Content.ReadAsByteArrayAsync());
|
||||
Assert.Equal("Manually Chunked", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,43 +88,28 @@ namespace Microsoft.Net.Http.Server
|
|||
Assert.Equal(new byte[30], await response.Content.ReadAsByteArrayAsync());
|
||||
}
|
||||
}
|
||||
/* TODO: response protocol
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseBody_Http10WriteNoHeaders_DefaultsConnectionClose()
|
||||
public async Task ResponseBody_WriteContentLengthNoneWritten_Aborts()
|
||||
{
|
||||
using (Utilities.CreateHttpServer(env =>
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
env["owin.ResponseProtocol"] = "HTTP/1.0";
|
||||
env.Get<Stream>("owin.ResponseBody").Write(new byte[10], 0, 10);
|
||||
return env.Get<Stream>("owin.ResponseBody").WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
||||
Assert.Equal(200, (int)response.StatusCode);
|
||||
Assert.Equal(new Version(1, 1), response.Version); // Http.Sys won't transmit 1.0
|
||||
IEnumerable<string> ignored;
|
||||
Assert.False(response.Content.Headers.TryGetValues("content-length", out ignored), "Content-Length");
|
||||
Assert.Null(response.Headers.TransferEncodingChunked);
|
||||
Assert.Equal(new byte[20], await response.Content.ReadAsByteArrayAsync());
|
||||
}
|
||||
}
|
||||
*/
|
||||
/* TODO: Why does this test time out?
|
||||
[Fact]
|
||||
public async Task ResponseBody_WriteContentLengthNoneWritten_Throws()
|
||||
{
|
||||
using (var server = Utilities.CreateHttpServer())
|
||||
{
|
||||
Task<HttpResponseMessage> responseTask = SendRequestAsync(Address);
|
||||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Response.Headers["Content-lenGth"] = new[] { " 20 " };
|
||||
context.Response.Headers["Content-lenGth"] = " 20 ";
|
||||
context.Dispose();
|
||||
|
||||
// HttpClient retries the request because it didn't get a response.
|
||||
context = await server.GetContextAsync();
|
||||
context.Response.Headers["Content-lenGth"] = " 20 ";
|
||||
context.Dispose();
|
||||
|
||||
await Assert.ThrowsAsync<HttpRequestException>(() => responseTask);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseBody_WriteContentLengthNotEnoughWritten_Throws()
|
||||
{
|
||||
|
|
|
@ -4,6 +4,7 @@ using System;
|
|||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
|
@ -12,7 +13,7 @@ namespace Microsoft.Net.Http.Server
|
|||
public class ResponseHeaderTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_ServerSendsDefaultHeaders_Success()
|
||||
public async Task ResponseHeaders_11Request_ServerSendsDefaultHeaders()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
@ -33,6 +34,143 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_10Request_ServerSendsDefaultHeaders()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(3, response.Headers.Count());
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.True(response.Headers.Date.HasValue);
|
||||
Assert.Equal("Microsoft-HTTPAPI/2.0", response.Headers.Server.ToString());
|
||||
Assert.Equal(1, response.Content.Headers.Count());
|
||||
Assert.Equal(0, response.Content.Headers.ContentLength);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_11HeadRequest_ServerSendsDefaultHeaders()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(3, response.Headers.Count());
|
||||
Assert.True(response.Headers.TransferEncodingChunked.Value);
|
||||
Assert.True(response.Headers.Date.HasValue);
|
||||
Assert.Equal("Microsoft-HTTPAPI/2.0", response.Headers.Server.ToString());
|
||||
Assert.False(response.Content.Headers.Contains("Content-Length"));
|
||||
Assert.Equal(0, response.Content.Headers.Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_10HeadRequest_ServerSendsDefaultHeaders()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address, usehttp11: false);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(3, response.Headers.Count());
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.True(response.Headers.Date.HasValue);
|
||||
Assert.Equal("Microsoft-HTTPAPI/2.0", response.Headers.Server.ToString());
|
||||
Assert.False(response.Content.Headers.Contains("Content-Length"));
|
||||
Assert.Equal(0, response.Content.Headers.Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_11HeadRequestWithContentLength_Success()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Response.ContentLength = 20;
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(2, response.Headers.Count());
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.True(response.Headers.Date.HasValue);
|
||||
Assert.Equal("Microsoft-HTTPAPI/2.0", response.Headers.Server.ToString());
|
||||
Assert.Equal(1, response.Content.Headers.Count());
|
||||
Assert.Equal(20, response.Content.Headers.ContentLength);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_11RequestStatusCodeWithoutBody_NoContentLengthOrChunkedOrClose()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Response.StatusCode = 204; // No Content
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(2, response.Headers.Count());
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.True(response.Headers.Date.HasValue);
|
||||
Assert.Equal("Microsoft-HTTPAPI/2.0", response.Headers.Server.ToString());
|
||||
Assert.False(response.Content.Headers.Contains("Content-Length"));
|
||||
Assert.Equal(0, response.Content.Headers.Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_11HeadRequestStatusCodeWithoutBody_NoContentLengthOrChunkedOrClose()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
Task<HttpResponseMessage> responseTask = SendHeadRequestAsync(address);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Response.StatusCode = 204; // No Content
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(2, response.Headers.Count());
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.True(response.Headers.Date.HasValue);
|
||||
Assert.Equal("Microsoft-HTTPAPI/2.0", response.Headers.Server.ToString());
|
||||
Assert.False(response.Content.Headers.Contains("Content-Length"));
|
||||
Assert.Equal(0, response.Content.Headers.Count());
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_ServerSendsSingleValueKnownHeaders_Success()
|
||||
{
|
||||
|
@ -127,43 +265,6 @@ namespace Microsoft.Net.Http.Server
|
|||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
}
|
||||
}
|
||||
/* TODO:
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_SendsHttp10_Gets11Close()
|
||||
{
|
||||
using (Utilities.CreateHttpServer(env =>
|
||||
{
|
||||
env["owin.ResponseProtocol"] = "HTTP/1.0";
|
||||
return Task.FromResult(0);
|
||||
}))
|
||||
{
|
||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_SendsHttp10WithBody_Gets11Close()
|
||||
{
|
||||
using (Utilities.CreateHttpServer(env =>
|
||||
{
|
||||
env["owin.ResponseProtocol"] = "HTTP/1.0";
|
||||
return env.Get<Stream>("owin.ResponseBody").WriteAsync(new byte[10], 0, 10);
|
||||
}))
|
||||
{
|
||||
HttpResponseMessage response = await SendRequestAsync(Address);
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.False(response.Content.Headers.Contains("Content-Length"));
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_HTTP10Request_Gets11Close()
|
||||
|
@ -171,26 +272,21 @@ namespace Microsoft.Net.Http.Server
|
|||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, address);
|
||||
request.Version = new Version(1, 0);
|
||||
Task<HttpResponseMessage> responseTask = client.SendAsync(request);
|
||||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Dispose();
|
||||
var context = await server.GetContextAsync();
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
}
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_HTTP10Request_RemovesChunkedHeader()
|
||||
public async Task ResponseHeaders_HTTP10Request_AllowsManualChunking()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
@ -204,20 +300,41 @@ namespace Microsoft.Net.Http.Server
|
|||
var context = await server.GetContextAsync();
|
||||
var responseHeaders = context.Response.Headers;
|
||||
responseHeaders["Transfer-Encoding"] = "chunked";
|
||||
await context.Response.Body.WriteAsync(new byte[10], 0, 10);
|
||||
var responseBytes = Encoding.ASCII.GetBytes("10\r\nManually Chunked\r\n0\r\n\r\n");
|
||||
await context.Response.Body.WriteAsync(responseBytes, 0, responseBytes.Length);
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.False(response.Headers.TransferEncodingChunked.HasValue);
|
||||
Assert.True(response.Headers.TransferEncodingChunked.Value);
|
||||
Assert.False(response.Content.Headers.Contains("Content-Length"));
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection"));
|
||||
Assert.Equal("Manually Chunked", await response.Content.ReadAsStringAsync());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseHeaders_HTTP10KeepAliveRequest_Gets11Close()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
{
|
||||
// Http.Sys does not support 1.0 keep-alives.
|
||||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, usehttp11: false, sendKeepAlive: true);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Dispose();
|
||||
|
||||
HttpResponseMessage response = await responseTask;
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.Equal(new Version(1, 1), response.Version);
|
||||
Assert.True(response.Headers.ConnectionClose.Value);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Headers_FlushSendsHeaders_Success()
|
||||
{
|
||||
|
@ -290,11 +407,33 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> SendRequestAsync(string uri)
|
||||
private async Task<HttpResponseMessage> SendRequestAsync(string uri, bool usehttp11 = true, bool sendKeepAlive = false)
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
return await client.GetAsync(uri);
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
||||
if (!usehttp11)
|
||||
{
|
||||
request.Version = new Version(1, 0);
|
||||
}
|
||||
if (sendKeepAlive)
|
||||
{
|
||||
request.Headers.Add("Connection", "Keep-Alive");
|
||||
}
|
||||
return await client.SendAsync(request);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<HttpResponseMessage> SendHeadRequestAsync(string uri, bool usehttp11 = true)
|
||||
{
|
||||
using (HttpClient client = new HttpClient())
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Head, uri);
|
||||
if (!usehttp11)
|
||||
{
|
||||
request.Version = new Version(1, 0);
|
||||
}
|
||||
return await client.SendAsync(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_Chunked_Chunked()
|
||||
public async Task ResponseSendFile_Unspecified_Chunked()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
@ -92,7 +92,6 @@ namespace Microsoft.Net.Http.Server
|
|||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Response.Headers["Transfer-EncodinG"] = "CHUNKED";
|
||||
await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
|
||||
context.Dispose();
|
||||
|
||||
|
@ -106,7 +105,7 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_MultipleChunks_Chunked()
|
||||
public async Task ResponseSendFile_MultipleWrites_Chunked()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
@ -114,7 +113,6 @@ namespace Microsoft.Net.Http.Server
|
|||
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
|
||||
|
||||
var context = await server.GetContextAsync();
|
||||
context.Response.Headers["Transfer-EncodinG"] = "CHUNKED";
|
||||
await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
|
||||
await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None);
|
||||
context.Dispose();
|
||||
|
@ -129,7 +127,7 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_ChunkedHalfOfFile_Chunked()
|
||||
public async Task ResponseSendFile_HalfOfFile_Chunked()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
@ -150,7 +148,7 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_ChunkedOffsetOutOfRange_Throws()
|
||||
public async Task ResponseSendFile_OffsetOutOfRange_Throws()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
@ -167,7 +165,7 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_ChunkedCountOutOfRange_Throws()
|
||||
public async Task ResponseSendFile_CountOutOfRange_Throws()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
@ -184,7 +182,7 @@ namespace Microsoft.Net.Http.Server
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResponseSendFile_ChunkedCount0_Chunked()
|
||||
public async Task ResponseSendFile_Count0_Chunked()
|
||||
{
|
||||
string address;
|
||||
using (var server = Utilities.CreateHttpServer(out address))
|
||||
|
|
Загрузка…
Ссылка в новой задаче