ln.http/ln.http/Http1XConnection.cs

92 lines
3.5 KiB
C#

using System;
using System.IO;
using System.Net;
using System.Text;
namespace ln.http;
public class Http1XConnection : HttpConnection
{
bool _keepAlive;
public Http1XConnection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method, Uri uri, HttpVersion httpVersion)
: base(listener, remoteEndpoint, connectionStream, method, uri, httpVersion)
{
if (httpVersion == HttpVersion.HTTP11)
_keepAlive = true;
}
public override void Run()
{
string _method = Method;
Uri _requestUri = RequestUri;
HttpVersion _httpVersion = HttpVersion;
HeaderContainer headerContainer = new HeaderContainer();
while (ConnectionStream.CanRead && ConnectionStream.CanWrite)
{
headerContainer.Clear();
headerContainer.Read(ConnectionStream);
if (
headerContainer.TryGetHeader("connection", out Header connectionHeader)
)
{
switch (connectionHeader.Value)
{
case "close":
_keepAlive = false;
break;
case "keep-alive":
_keepAlive = true;
break;
}
}
HttpRequestStream requestStream = null;
if (headerContainer.TryGetInteger("content-length", out int contentLength))
requestStream = new HttpRequestStream(ConnectionStream, contentLength);
HttpRequestContext requestContext = new HttpRequestContext(Listener, this, ConnectionStream, new HttpRequest(_method, _requestUri, _httpVersion, false, headerContainer, requestStream));
Listener.Dispatch(requestContext);
if (!ConnectionStream.CanWrite && !ConnectionStream.CanRead)
break;
SendResponse(requestContext);
ConnectionStream.Flush();
string responseConnectionHeader = requestContext.Response.GetHeader("connection");
_keepAlive = responseConnectionHeader switch
{
"close" => false,
"keep-alive" => true,
_ => _keepAlive
};
requestContext.Dispose();
if (!_keepAlive)
break;
if (!HttpConnection.ReadRequestLine(ConnectionStream, out _method, out _requestUri, out _httpVersion))
break;
}
}
public override void SendResponse(HttpRequestContext requestContext)
{
foreach (var httpCookie in requestContext.Response.Cookies)
requestContext.Response.Headers.Add("Set-Cookie", httpCookie.ToString());
string statusLine = $"{HttpVersionSupport.ToString(requestContext.Request.HttpVersion)} {(int)requestContext.Response.HttpStatusCode} {requestContext.Response.HttpStatusCode.ToString()}\r\n";
byte[] statusLineBytes = Encoding.ASCII.GetBytes(statusLine);
requestContext.ConnectionStream.Write(statusLineBytes, 0, statusLineBytes.Length);
if (!requestContext.Response.Headers.Contains("content-type"))
requestContext.Response.Headers.Set("content-type", requestContext.Response.HttpContent?.ContentType);
requestContext.Response.Headers.Set("content-length", requestContext.Response.HttpContent?.Length.ToString() ?? "0");
requestContext.Response.Headers.CopyTo(requestContext.ConnectionStream);
requestContext.Response.HttpContent?.CopyTo(requestContext.ConnectionStream);
}
}