Fixed buggy request line interpretation

master
Harald Wolff 2023-08-17 17:32:15 +02:00
parent 16f1b2cf06
commit 7511bf112b
8 changed files with 45 additions and 51 deletions

View File

@ -9,12 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.tests", "ln.http.te
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.service", "ln.http.service\ln.http.service.csproj", "{FE139A5A-A388-4656-AD15-149012EDB9D0}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.service", "ln.http.service\ln.http.service.csproj", "{FE139A5A-A388-4656-AD15-149012EDB9D0}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.protocols.helper", "..\ln.protocols.helper\ln.protocols.helper.csproj", "{1C1D3A17-A615-4686-90BD-F0E221EAC89C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.templates", "..\ln.templates\ln.http.templates\ln.http.templates.csproj", "{45709176-EA57-4BB3-815B-91D161CEB7A6}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.templates", "..\ln.templates\ln.http.templates\ln.http.templates.csproj", "{45709176-EA57-4BB3-815B-91D161CEB7A6}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.templates", "..\ln.templates\ln.templates\ln.templates.csproj", "{D6BA640C-352F-41BF-85EF-4B76FD928BEC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.helpers", "ln.http.helpers\ln.http.helpers.csproj", "{FAC3F9BE-6C09-4523-8584-2BD5B08BB70D}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ln.http.helpers", "ln.http.helpers\ln.http.helpers.csproj", "{FAC3F9BE-6C09-4523-8584-2BD5B08BB70D}"
EndProject EndProject
Global Global
@ -63,26 +59,10 @@ Global
{FE139A5A-A388-4656-AD15-149012EDB9D0}.Release|x86.ActiveCfg = Release|Any CPU {FE139A5A-A388-4656-AD15-149012EDB9D0}.Release|x86.ActiveCfg = Release|Any CPU
{FE139A5A-A388-4656-AD15-149012EDB9D0}.Release|x86.Build.0 = Release|Any CPU {FE139A5A-A388-4656-AD15-149012EDB9D0}.Release|x86.Build.0 = Release|Any CPU
{FE139A5A-A388-4656-AD15-149012EDB9D0}.Release|Any CPU.Deploy.0 = Release|Any CPU {FE139A5A-A388-4656-AD15-149012EDB9D0}.Release|Any CPU.Deploy.0 = Release|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Debug|x64.ActiveCfg = Debug|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Debug|x64.Build.0 = Debug|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Debug|x86.ActiveCfg = Debug|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Debug|x86.Build.0 = Debug|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Release|Any CPU.Build.0 = Release|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Release|x64.ActiveCfg = Release|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Release|x64.Build.0 = Release|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Release|x86.ActiveCfg = Release|Any CPU
{1C1D3A17-A615-4686-90BD-F0E221EAC89C}.Release|x86.Build.0 = Release|Any CPU
{45709176-EA57-4BB3-815B-91D161CEB7A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {45709176-EA57-4BB3-815B-91D161CEB7A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{45709176-EA57-4BB3-815B-91D161CEB7A6}.Debug|Any CPU.Build.0 = Debug|Any CPU {45709176-EA57-4BB3-815B-91D161CEB7A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45709176-EA57-4BB3-815B-91D161CEB7A6}.Release|Any CPU.ActiveCfg = Release|Any CPU {45709176-EA57-4BB3-815B-91D161CEB7A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45709176-EA57-4BB3-815B-91D161CEB7A6}.Release|Any CPU.Build.0 = Release|Any CPU {45709176-EA57-4BB3-815B-91D161CEB7A6}.Release|Any CPU.Build.0 = Release|Any CPU
{D6BA640C-352F-41BF-85EF-4B76FD928BEC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6BA640C-352F-41BF-85EF-4B76FD928BEC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6BA640C-352F-41BF-85EF-4B76FD928BEC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6BA640C-352F-41BF-85EF-4B76FD928BEC}.Release|Any CPU.Build.0 = Release|Any CPU
{FAC3F9BE-6C09-4523-8584-2BD5B08BB70D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FAC3F9BE-6C09-4523-8584-2BD5B08BB70D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FAC3F9BE-6C09-4523-8584-2BD5B08BB70D}.Debug|Any CPU.Build.0 = Debug|Any CPU {FAC3F9BE-6C09-4523-8584-2BD5B08BB70D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FAC3F9BE-6C09-4523-8584-2BD5B08BB70D}.Release|Any CPU.ActiveCfg = Release|Any CPU {FAC3F9BE-6C09-4523-8584-2BD5B08BB70D}.Release|Any CPU.ActiveCfg = Release|Any CPU

View File

@ -9,8 +9,8 @@ public class Http1XConnection : HttpConnection
{ {
bool _keepAlive; bool _keepAlive;
public Http1XConnection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method, Uri uri, HttpVersion httpVersion) public Http1XConnection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method, string requestUriLine, HttpVersion httpVersion)
: base(listener, remoteEndpoint, connectionStream, method, uri, httpVersion) : base(listener, remoteEndpoint, connectionStream, method, requestUriLine, httpVersion)
{ {
if (httpVersion == HttpVersion.HTTP11) if (httpVersion == HttpVersion.HTTP11)
_keepAlive = true; _keepAlive = true;
@ -19,15 +19,18 @@ public class Http1XConnection : HttpConnection
public override void Run() public override void Run()
{ {
string _method = Method; string _method = Method;
Uri _requestUri = RequestUri;
HttpVersion _httpVersion = HttpVersion; HttpVersion _httpVersion = HttpVersion;
HeaderContainer headerContainer = new HeaderContainer(); HeaderContainer headerContainer = new HeaderContainer();
string _requestUriLine = RequestUriLine;
while (ConnectionStream.CanRead && ConnectionStream.CanWrite) while (ConnectionStream.CanRead && ConnectionStream.CanWrite)
{ {
headerContainer.Clear(); headerContainer.Clear();
headerContainer.Read(ConnectionStream); headerContainer.Read(ConnectionStream);
Uri BaseURI = new Uri($"{(Listener is TlsListener ? "https" : "http")}://{headerContainer.Get("host")}");
Uri RequestUri = new Uri(BaseURI, _requestUriLine);
if ( if (
headerContainer.TryGetHeader("connection", out Header connectionHeader) headerContainer.TryGetHeader("connection", out Header connectionHeader)
) )
@ -45,9 +48,18 @@ public class Http1XConnection : HttpConnection
HttpRequestStream requestStream = null; HttpRequestStream requestStream = null;
if (headerContainer.TryGetInteger("content-length", out int contentLength)) if (headerContainer.TryGetInteger("content-length", out int contentLength))
{
if (headerContainer.TryGetValue("Expect", out string expectValue) && expectValue.Equals("100-continue"))
{
string statusLine = $"{HttpVersionSupport.ToString(_httpVersion)} 417 expectation failed\r\n";
byte[] statusLineBytes = Encoding.ASCII.GetBytes(statusLine);
ConnectionStream.Write(statusLineBytes);
break;
}
requestStream = new HttpRequestStream(ConnectionStream, contentLength); requestStream = new HttpRequestStream(ConnectionStream, contentLength);
}
HttpRequestContext requestContext = new HttpRequestContext(Listener, this, ConnectionStream, new HttpRequest(_method, _requestUri, _httpVersion, false, headerContainer, requestStream)); HttpRequestContext requestContext = new HttpRequestContext(Listener, this, ConnectionStream, new HttpRequest(_method, RequestUri, _httpVersion, false, headerContainer, requestStream));
Listener.Dispatch(requestContext); Listener.Dispatch(requestContext);
if (!ConnectionStream.CanWrite && !ConnectionStream.CanRead) if (!ConnectionStream.CanWrite && !ConnectionStream.CanRead)
@ -69,7 +81,7 @@ public class Http1XConnection : HttpConnection
if (!_keepAlive) if (!_keepAlive)
break; break;
if (!HttpConnection.ReadRequestLine(ConnectionStream, out _method, out _requestUri, out _httpVersion)) if (!HttpConnection.ReadRequestLine(ConnectionStream, out _method, out _requestUriLine, out _httpVersion))
break; break;
} }
} }

View File

@ -6,8 +6,8 @@ namespace ln.http;
public class Http2Connection : HttpConnection public class Http2Connection : HttpConnection
{ {
public Http2Connection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method, Uri uri, HttpVersion httpVersion) public Http2Connection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method, string requestUriLine, HttpVersion httpVersion)
: base(listener, remoteEndpoint, connectionStream, method, uri, httpVersion) : base(listener, remoteEndpoint, connectionStream, method, requestUriLine, httpVersion)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View File

@ -13,18 +13,20 @@ namespace ln.http
public IPEndPoint RemoteEndpoint { get; } public IPEndPoint RemoteEndpoint { get; }
public Stream ConnectionStream { get; } public Stream ConnectionStream { get; }
public string Method { get; } public string Method { get; }
public Uri RequestUri { get; } //public Uri RequestUri { get; }
public HttpVersion HttpVersion { get; } public HttpVersion HttpVersion { get; }
public string RequestUriLine { get; set; }
public HttpConnection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method, public HttpConnection(Listener listener, IPEndPoint remoteEndpoint, Stream connectionStream, string method,
Uri uri, HttpVersion httpVersion) String requestUriLine, HttpVersion httpVersion)
{ {
Listener = listener; Listener = listener;
RemoteEndpoint = remoteEndpoint; RemoteEndpoint = remoteEndpoint;
ConnectionStream = connectionStream; ConnectionStream = connectionStream;
Method = method; Method = method;
RequestUri = uri; RequestUriLine = requestUriLine;
HttpVersion = httpVersion; HttpVersion = httpVersion;
} }
@ -60,7 +62,7 @@ namespace ln.http
return null; return null;
} }
public static bool ReadRequestLine(Stream stream, out string method, out Uri requestUri, public static bool ReadRequestLine(Stream stream, out string method, out string requestUri,
out HttpVersion httpVersion) out HttpVersion httpVersion)
{ {
string requestLine = ReadLine(stream); string requestLine = ReadLine(stream);
@ -78,7 +80,7 @@ namespace ln.http
if ((idxSpace1 > 0) && (idxSpace2 > 0)) if ((idxSpace1 > 0) && (idxSpace2 > 0))
{ {
method = requestLine.Substring(0, idxSpace1); method = requestLine.Substring(0, idxSpace1);
requestUri = new Uri(requestLine.Substring(idxSpace1 + 1, (idxSpace2 - idxSpace1 - 1))); requestUri = requestLine.Substring(idxSpace1 + 1, (idxSpace2 - idxSpace1 - 1));
string protocol = requestLine.Substring(idxSpace2 + 1); string protocol = requestLine.Substring(idxSpace2 + 1);
httpVersion = HttpVersion.None; httpVersion = HttpVersion.None;
@ -98,8 +100,8 @@ namespace ln.http
return false; return false;
} }
public abstract void SendResponse(HttpRequestContext requestContext); public abstract void SendResponse(HttpRequestContext requestContext);
static Uri Http2PrefaceUri = new Uri("*"); private static string Http2PrefaceUri = "*";
} }
} }

View File

@ -103,7 +103,7 @@ namespace ln.http
.ConvertFromInvariantString(parameterValue); .ConvertFromInvariantString(parameterValue);
} }
} }
else if (_argumentSourceAttributes[n].ArgumentSource == HttpArgumentSource.CONTENT) else if ((_argumentSourceAttributes[n].ArgumentSource == HttpArgumentSource.CONTENT) && (requestContext.Request.Headers.Contains("content-length")))
{ {
if (_parameterInfos[n].ParameterType.Equals(typeof(Stream))) if (_parameterInfos[n].ParameterType.Equals(typeof(Stream)))
{ {

View File

@ -13,16 +13,16 @@ public class HttpRequestStream : Stream
public HttpRequestStream(Stream connectionStream, int length) public HttpRequestStream(Stream connectionStream, int length)
{ {
byte[] transferBuffer; byte[] transferBuffer;
if (length <= MemoryLimit) // if (length <= MemoryLimit)
{ // {
transferBuffer = new byte[length]; // transferBuffer = new byte[length];
if (connectionStream.Read(transferBuffer, 0, transferBuffer.Length) != length) // if (connectionStream.ReadExactly(transferBuffer, 0, transferBuffer.Length) != length)
throw new IOException(); // throw new IOException();
//
_stream = new MemoryStream(transferBuffer); // _stream = new MemoryStream(transferBuffer);
} // }
else // else
{ // {
_tempFileName = Path.GetTempFileName(); _tempFileName = Path.GetTempFileName();
_stream = new FileStream(_tempFileName, FileMode.Open, FileAccess.ReadWrite); _stream = new FileStream(_tempFileName, FileMode.Open, FileAccess.ReadWrite);
@ -36,7 +36,7 @@ public class HttpRequestStream : Stream
} }
_stream.Position = 0; _stream.Position = 0;
} // }
} }
public override int Read(byte[] buffer, int offset, int count) => _stream.Read(buffer, offset, count); public override int Read(byte[] buffer, int offset, int count) => _stream.Read(buffer, offset, count);

View File

@ -72,7 +72,7 @@ public class Listener : IDisposable
protected virtual void Accepted(Socket connectedSocket, Stream connectionStream) protected virtual void Accepted(Socket connectedSocket, Stream connectionStream)
{ {
if (HttpConnection.ReadRequestLine(connectionStream, out string method, out Uri requestUri, out HttpVersion httpVersion)) if (HttpConnection.ReadRequestLine(connectionStream, out string method, out string requestUri, out HttpVersion httpVersion))
{ {
if ((AcceptedHttpVersion & httpVersion) == HttpVersion.None) if ((AcceptedHttpVersion & httpVersion) == HttpVersion.None)
return; return;

View File

@ -9,9 +9,9 @@
<Copyright>(c) 2020 Harald Wolff-Thobaben</Copyright> <Copyright>(c) 2020 Harald Wolff-Thobaben</Copyright>
<PackageTags>http server</PackageTags> <PackageTags>http server</PackageTags>
<LangVersion>default</LangVersion> <LangVersion>default</LangVersion>
<PackageVersion>0.9.5</PackageVersion> <PackageVersion>0.9.8-preview4</PackageVersion>
<AssemblyVersion>0.6.2.0</AssemblyVersion> <AssemblyVersion>0.6.2.0</AssemblyVersion>
<TargetFrameworks>net5.0;net6.0</TargetFrameworks> <TargetFramework>net7.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>