178 lines
6.7 KiB
C#
178 lines
6.7 KiB
C#
// Copyright (c) .NET Foundation. All rights reserved.
|
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
|
|
using System.Globalization;
|
|
using System.Net;
|
|
using System.Net.Http;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Testing.xunit;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using Xunit;
|
|
|
|
namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
|
|
{
|
|
public class RequestTests
|
|
{
|
|
[Theory]
|
|
[InlineData(10 * 1024 * 1024, true)]
|
|
// In the following dataset, send at least 2GB.
|
|
// Never change to a lower value, otherwise regression testing for
|
|
// https://github.com/aspnet/KestrelHttpServer/issues/520#issuecomment-188591242
|
|
// will be lost.
|
|
[InlineData((long)int.MaxValue + 1, false)]
|
|
public void LargeUpload(long contentLength, bool checkBytes)
|
|
{
|
|
const int bufferLength = 1024 * 1024;
|
|
Assert.True(contentLength % bufferLength == 0, $"{nameof(contentLength)} sent must be evenly divisible by {bufferLength}.");
|
|
Assert.True(bufferLength % 256 == 0, $"{nameof(bufferLength)} must be evenly divisible by 256");
|
|
|
|
var builder = new WebHostBuilder()
|
|
.UseKestrel()
|
|
.UseUrls("http://127.0.0.1:0/")
|
|
.Configure(app =>
|
|
{
|
|
app.Run(async context =>
|
|
{
|
|
// Read the full request body
|
|
long total = 0;
|
|
var receivedBytes = new byte[bufferLength];
|
|
var received = 0;
|
|
while ((received = await context.Request.Body.ReadAsync(receivedBytes, 0, receivedBytes.Length)) > 0)
|
|
{
|
|
if (checkBytes)
|
|
{
|
|
for (var i = 0; i < received; i++)
|
|
{
|
|
Assert.Equal((byte)((total + i) % 256), receivedBytes[i]);
|
|
}
|
|
}
|
|
|
|
total += received;
|
|
}
|
|
|
|
await context.Response.WriteAsync(total.ToString(CultureInfo.InvariantCulture));
|
|
});
|
|
});
|
|
|
|
using (var host = builder.Build())
|
|
{
|
|
host.Start();
|
|
|
|
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
|
|
{
|
|
socket.Connect(new IPEndPoint(IPAddress.Loopback, host.GetPort()));
|
|
socket.Send(Encoding.ASCII.GetBytes($"POST / HTTP/1.0\r\nContent-Length: {contentLength}\r\n\r\n"));
|
|
|
|
var contentBytes = new byte[bufferLength];
|
|
|
|
if (checkBytes)
|
|
{
|
|
for (var i = 0; i < contentBytes.Length; i++)
|
|
{
|
|
contentBytes[i] = (byte)i;
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i < contentLength / contentBytes.Length; i++)
|
|
{
|
|
socket.Send(contentBytes);
|
|
}
|
|
|
|
var response = new StringBuilder();
|
|
var responseBytes = new byte[4096];
|
|
var received = 0;
|
|
while ((received = socket.Receive(responseBytes)) > 0)
|
|
{
|
|
response.Append(Encoding.ASCII.GetString(responseBytes, 0, received));
|
|
}
|
|
|
|
Assert.Contains(contentLength.ToString(CultureInfo.InvariantCulture), response.ToString());
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public Task RemoteIPv4Address()
|
|
{
|
|
return TestRemoteIPAddress("127.0.0.1", "127.0.0.1", "127.0.0.1");
|
|
}
|
|
|
|
[ConditionalFact]
|
|
[IPv6SupportedCondition]
|
|
public Task RemoteIPv6Address()
|
|
{
|
|
return TestRemoteIPAddress("[::1]", "[::1]", "::1");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task DoesNotHangOnConnectionCloseRequest()
|
|
{
|
|
var builder = new WebHostBuilder()
|
|
.UseKestrel()
|
|
.UseUrls($"http://127.0.0.1:0")
|
|
.Configure(app =>
|
|
{
|
|
app.Run(async context =>
|
|
{
|
|
await context.Response.WriteAsync("hello, world");
|
|
});
|
|
});
|
|
|
|
using (var host = builder.Build())
|
|
using (var client = new HttpClient())
|
|
{
|
|
host.Start();
|
|
|
|
client.DefaultRequestHeaders.Connection.Clear();
|
|
client.DefaultRequestHeaders.Connection.Add("close");
|
|
|
|
var response = await client.GetAsync($"http://localhost:{host.GetPort()}/");
|
|
response.EnsureSuccessStatusCode();
|
|
}
|
|
}
|
|
|
|
private async Task TestRemoteIPAddress(string registerAddress, string requestAddress, string expectAddress)
|
|
{
|
|
var builder = new WebHostBuilder()
|
|
.UseKestrel()
|
|
.UseUrls($"http://{registerAddress}:0")
|
|
.Configure(app =>
|
|
{
|
|
app.Run(async context =>
|
|
{
|
|
var connection = context.Connection;
|
|
await context.Response.WriteAsync(JsonConvert.SerializeObject(new
|
|
{
|
|
RemoteIPAddress = connection.RemoteIpAddress?.ToString(),
|
|
RemotePort = connection.RemotePort,
|
|
LocalIPAddress = connection.LocalIpAddress?.ToString(),
|
|
LocalPort = connection.LocalPort
|
|
}));
|
|
});
|
|
});
|
|
|
|
using (var host = builder.Build())
|
|
using (var client = new HttpClient())
|
|
{
|
|
host.Start();
|
|
|
|
var response = await client.GetAsync($"http://{requestAddress}:{host.GetPort()}/");
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
var connectionFacts = await response.Content.ReadAsStringAsync();
|
|
Assert.NotEmpty(connectionFacts);
|
|
|
|
var facts = JsonConvert.DeserializeObject<JObject>(connectionFacts);
|
|
Assert.Equal(expectAddress, facts["RemoteIPAddress"].Value<string>());
|
|
Assert.NotEmpty(facts["RemotePort"].Value<string>());
|
|
}
|
|
}
|
|
}
|
|
}
|