This change fixes the in-process marshalling of TCP handles on Mac and Linux
that is used to support having multiple threads accepting connections from
multiple loops.
On these two platforms, the ReadStart callback somtimes gets called with a
status and pipe_pending_count equal to zero. Now when the status is zero
just exit the callback without closing the pipe.
This change more closely follows the example at
https://nikhilm.github.io/uvbook/processes.html#sending-file-descriptors-over-pipes
- Previously an incomplete chunked response would be written instead.
- Add test to verify Content-Length: 0 is set automatically.
- Add test to verify HTTP/1.0 keep-alive isn't used if no Content-Length
is set for the response.
- Add tests to verify errors are handled properly after chunked writes.
#173
The common use-case for Kestrel in production will be behind a reverse proxy such as Nginx. In cases where the reverse proxy is located on the same machine as the application, connecting via a UNIX socket is more efficient than a TCP socket, as it avoids going through the network layer. Accessing 127.0.0.1 through TCP still needs to initiate a TCP connection and perform handshaking, checksumming, etc, all of which is avoided by using UNIX sockets.
- Moved TCP-specific stuff from Listener into new TcpListener class (same with ListenerPrimary and ListenerSecondary)
- Made Listener abstract
- Created new PipeListener. Note that while the use case is for UNIX sockets, this is called "Pipe" in uv, so I've called this "PipeListener" so the terminology is consistant
- Uses "unix" URL scheme to determine whether to use socket. "http://127.0.0.1:5000" is for listening via TCP while "unix:///var/run/kestrel-test.sock" is for listening via UNIX socket
#156
- Zero length writes would previously be interpreted as the end of response
- Optimize writing the chunked response suffix
- Add tests for automatic response chunking
- If OnStarting is being called after the app func has completed, return a 500.
- If Onstarting is being called due to a call to write, throw from write.
Calling uv_read_start on a named pipe with a larger than necessary buffer
would cause pieces of the next uv_ipc_frame_uv_stream struct to be read into
the uv_read_start buffer when a lot of tcp handles were passed quickly over
the pipe.
This prevented the struct from properly being queued for the next call to
uv_accept to consume. The empty queue caused the call to uv_accept in
ListenerSecondary to fail and return WSAEWOULDBLOCK leaving the connection
in a zombie state.