Skip to content

Commit

Permalink
Refactored RuriLib.Http and RuriLib.Http.Tests
Browse files Browse the repository at this point in the history
Also added missing comma-separated cookies handling logic
  • Loading branch information
openbullet committed Sep 8, 2024
1 parent 3ef3277 commit 479e1b9
Show file tree
Hide file tree
Showing 16 changed files with 2,133 additions and 2,125 deletions.
370 changes: 184 additions & 186 deletions RuriLib.Http.Tests/ProxyClientHandlerTests.cs

Large diffs are not rendered by default.

397 changes: 202 additions & 195 deletions RuriLib.Http.Tests/RLHttpClientTests.cs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions RuriLib.Http.Tests/RuriLib.Http.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<TargetFramework>net8.0</TargetFramework>

<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
Expand Down
14 changes: 14 additions & 0 deletions RuriLib.Http/Exceptions/RLHttpException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;

namespace RuriLib.Http.Exceptions;

/// <summary>
/// An exception that is thrown when an HTTP request fails.
/// </summary>
public class RLHttpException : Exception
{
/// <summary>
/// Creates an RLHttpException with a <paramref name="message"/>.
/// </summary>
public RLHttpException(string message) : base(message) { }
}
11 changes: 5 additions & 6 deletions RuriLib.Http/Extensions/IListExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using System.Collections.Generic;

namespace RuriLib.Http.Extensions
namespace RuriLib.Http.Extensions;

internal static class ListExtensions
{
static internal class IListExtensions
{
public static void Add(this IList<KeyValuePair<string, string>> list, string key, object value)
=> list.Add(new KeyValuePair<string, string>(key, value.ToString()));
}
public static void Add(this IList<KeyValuePair<string, string>> list, string key, object value)
=> list.Add(new KeyValuePair<string, string>(key, value.ToString()!));
}
167 changes: 80 additions & 87 deletions RuriLib.Http/Helpers/ChunkedDecoderOptimized.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,117 +3,110 @@
using System.IO;
using System.Text;

namespace RuriLib.Http.Helpers
namespace RuriLib.Http.Helpers;

internal class ChunkedDecoderOptimized : IDisposable
{
internal class ChunkedDecoderOptimized : IDisposable
{
private long templength;
private static byte[] CRLF_Bytes = { 13, 10 };
// private long remaningchunklength;
private bool Isnewchunk = true;
// private AutoResetEvent manualResetEvent = new AutoResetEvent(true);
private long _tempLength;
private static readonly byte[] _crlfBytes = "\r\n"u8.ToArray();
private bool _isNewChunk = true;

public Stream DecodedStream { get; private set; }
public Stream DecodedStream { get; } = new MemoryStream(1024);

public bool Finished { get; private set; }
public bool Finished { get; private set; }

public ChunkedDecoderOptimized()
internal void Decode(ref ReadOnlySequence<byte> buff) => ParseNewChunk(ref buff);

private void ParseNewChunk(ref ReadOnlySequence<byte> buff)
{
if (_isNewChunk)
{
DecodedStream = new MemoryStream(1024);
_tempLength = GetChunkLength(ref buff);
_isNewChunk = false;
}

if (_tempLength == 0 && buff.Length >= 2)
{
Finished = true;
buff = buff.Slice(2);//skip last crlf
return;
}

internal void Decode(ref ReadOnlySequence<byte> buff) => ParseNewChunk(ref buff);
if (_tempLength == -1)
{
_isNewChunk = true;
return;
}

if (buff.Length > _tempLength + 2)
{
var chunk = buff.Slice(buff.Start, _tempLength);
WriteToStream(chunk);
_isNewChunk = true;
buff = buff.Slice(chunk.End);
buff = buff.Slice(2); //skip CRLF

ParseNewChunk(ref buff);
}
}

private void ParseNewChunk(ref ReadOnlySequence<byte> buff)
private int GetChunkLength(ref ReadOnlySequence<byte> buff)
{
if (buff.IsSingleSegment)
{
if (Isnewchunk)
var index = -1;
var span = buff.FirstSpan;
index = span.IndexOf(_crlfBytes);

if (index == -1)
{
templength = GetChunkLength(ref buff);
Isnewchunk = false;
// Console.WriteLine($"error payload: {Encoding.ASCII.GetString(buff.FirstSpan)}");
return -1;
}
if (templength == 0 && buff.Length >= 2)

var line = span[..index];
var pos = line.IndexOf((byte)';');
if (pos != -1)
{
Finished = true;
buff = buff.Slice(2);//skip last crlf
return;
}
else if (templength == -1)
{
Isnewchunk = true;
return;
}
if (buff.Length > templength + 2)
{
var chunk = buff.Slice(buff.Start, templength);
WritetoStream(chunk);
Isnewchunk = true;
buff = buff.Slice(chunk.End);
buff = buff.Slice(2); //skip CRLF

ParseNewChunk(ref buff);
line = line[..pos];
}
buff = buff.Slice(index + 2);
return Convert.ToInt32(Encoding.ASCII.GetString(line), 16);
}

private int GetChunkLength(ref ReadOnlySequence<byte> buff)
else
{
if (buff.IsSingleSegment)
var reader = new SequenceReader<byte>(buff);

if (!reader.TryReadTo(out ReadOnlySpan<byte> line, _crlfBytes.AsSpan()))
{
var index = -1;
var span = buff.FirstSpan;
index = span.IndexOf(CRLF_Bytes);
if (index != -1)
{
var line = span.Slice(0, index);
var pos = line.IndexOf((byte)';');
if (pos != -1)
{
line = line.Slice(0, pos);
}
buff = buff.Slice(index + 2);
return Convert.ToInt32(Encoding.ASCII.GetString(line), 16);
}
else
{
// Console.WriteLine($"error payload: {Encoding.ASCII.GetString(buff.FirstSpan)}");
return -1;
}
// Console.WriteLine($"error payload: {Encoding.ASCII.GetString(buff.FirstSpan)}");
return -1;
}
else

var pos = line.IndexOf((byte)';');
if (pos > 0)
{
SequenceReader<byte> reader = new SequenceReader<byte>(buff);
if (reader.TryReadTo(out ReadOnlySpan<byte> line, CRLF_Bytes.AsSpan(), true))
{
var pos = line.IndexOf((byte)';');
if (pos > 0)
{
line = line.Slice(0, pos);
}
buff = buff.Slice(reader.Position);
return Convert.ToInt32(Encoding.ASCII.GetString(line), 16);
}
else
{
// Console.WriteLine($"error payload: {Encoding.ASCII.GetString(buff.FirstSpan)}");
return -1;
}
line = line[..pos];
}
buff = buff.Slice(reader.Position);
return Convert.ToInt32(Encoding.ASCII.GetString(line), 16);
}
}

private void WritetoStream(ReadOnlySequence<byte> buff)
private void WriteToStream(ReadOnlySequence<byte> buff)
{
if (buff.IsSingleSegment)
{
if (buff.IsSingleSegment)
{
DecodedStream.Write(buff.FirstSpan);
}
else
DecodedStream.Write(buff.FirstSpan);
}
else
{
foreach (var seg in buff)
{
foreach (var seg in buff)
{
DecodedStream.Write(seg.Span);
}
DecodedStream.Write(seg.Span);
}
}

public void Dispose() => DecodedStream?.Dispose();
}

public void Dispose() => DecodedStream.Dispose();
}
37 changes: 18 additions & 19 deletions RuriLib.Http/Helpers/ContentHelper.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
using System;
using System.Linq;

namespace RuriLib.Http.Helpers
namespace RuriLib.Http.Helpers;

internal static class ContentHelper
{
static internal class ContentHelper
{
//https://github.com/dotnet/corefx/blob/3e72ee5971db5d0bd46606fa672969adde29e307/src/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs
private static readonly string[] contentHeaders = new []
{
"Last-Modified",
"Expires",
"Content-Type",
"Content-Range",
"Content-MD5",
"Content-Location",
"Content-Length",
"Content-Language",
"Content-Encoding",
"Allow"
};
//https://github.com/dotnet/corefx/blob/3e72ee5971db5d0bd46606fa672969adde29e307/src/System.Net.Http/src/System/Net/Http/Headers/KnownHeaders.cs
private static readonly string[] _contentHeaders =
[
"Last-Modified",
"Expires",
"Content-Type",
"Content-Range",
"Content-MD5",
"Content-Location",
"Content-Length",
"Content-Language",
"Content-Encoding",
"Allow"
];

public static bool IsContentHeader(string name) => contentHeaders.Any(h => h.Equals(name, StringComparison.OrdinalIgnoreCase));
}
public static bool IsContentHeader(string name) => _contentHeaders.Any(h => h.Equals(name, StringComparison.OrdinalIgnoreCase));
}
Loading

0 comments on commit 479e1b9

Please sign in to comment.