Closed comphilip closed 9 years ago
Can you (do you want to) try to write test case?
Hi Bobris,
From TCPView tool, I found some thing interesting. My HttpWebRequest connect to Nowin server via IPv6. I debug my code and sure the HttpWebRequest.Close was called. While still the connection is not closed, it seems HttpWebRequest persist the connection (HTTP/1.1) even though adding Connection: close header.
I am still looking at it. Maybe it is HttpWebRequst behavior and has nothing with Nowin.
It should be possible to recreate it using just plain Socket - create Http/1.1 request by hand should not be too difficult.
Hi Boris,
You are right. It is my code problem. Thanks.
Hi Bobris, I find it is exactly a bug of Nowin.
using Microsoft.Owin.Hosting;
using Owin;
using System;
using System.Threading.Tasks;
namespace NowinServer {
class Program {
static void Main(string[] args) {
var options = new StartOptions {
ServerFactory = "Nowin",
Port = 8080
};
using (WebApp.Start<Startup>(options)) {
Console.WriteLine("Running a http server on port 8080");
Console.ReadKey();
}
}
}
public class Startup {
public void Configuration(IAppBuilder app) {
app.Use(async (context, task) => {
// wait 1 minute
Console.WriteLine("Start to wait 1 minute...");
using (context.Request.CallCancelled.Register(() => {
// if CallCancelled cancelled, following message should shown in console
Console.WriteLine("Request CallCancelled cancelled.");
})) {
//simulate long time operation, use context.Request.CallCancelled to stop processing if client disconnected.
try {
for (int i = 0; i < 60; ++i) {
await Task.Delay(TimeSpan.FromSeconds(1), context.Request.CallCancelled);
}
Console.WriteLine("Long operation completed.");
} catch (TaskCanceledException) {
Console.WriteLine("Long operation cancelled.");
}
if (context.Request.Path.Value == "/") {
context.Response.ContentType = "text/plain";
await context.Response.WriteAsync("Hello World!");
}
context.Response.StatusCode = 404;
}
});
}
}
}
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace TestClient {
class Program {
static void Main(string[] args) {
using (TcpClient client = new TcpClient()) {
Console.WriteLine("Connecting to Nowin Server");
client.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8080));
using (var connStream = client.GetStream()) {
Console.WriteLine("Send http request");
var request = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\n"
+ "Host: localhost:8080\r\n"
+ "\r\n");
connStream.Write(request, 0, request.Length);
connStream.Flush();
}
}
Console.WriteLine("Client closed.");
}
}
}
You are right this feature was missing, thanks for repro. Unfortunately I was not able to implemented it during one night (it is pretty complex to do it thread safe without too much locking), so need to continue on it later today...
This fix took me over 10 hours. It is big change and although all tests pass, please test it carefully.
Reproduce
Expected Result
owin.CallCancelled should be cancelled and server code registered callback should be called.
Now
owin.CallCancelled not cancelled on client TCP connection closed or dropped