Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 17 additions & 15 deletions src/Fluxzy.Core/Archiving/HeaderFieldInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

namespace Fluxzy
{
/// <summary>
/// Represent a header field
/// <summary>
/// Represent a header field
/// </summary>
[MessagePackObject]
public class HeaderFieldInfo
Expand Down Expand Up @@ -42,13 +42,15 @@ public override int GetHashCode()

public HeaderFieldInfo(HeaderField original, bool doNotForwardConnectionHeader = false)
{
Name = original.Name;
Value = original.Value;

// Materialize pooled Memory<char> slices into string-backed memory
// to prevent use-after-free when the ExchangeScope returns the buffer to the pool
Name = original.Name.ToString().AsMemory();
Value = original.Value.ToString().AsMemory();

Forwarded = !Http11Constants.IsNonForwardableHeader(original.Name);

if (doNotForwardConnectionHeader && Forwarded && Http11Constants.UnEditableHeaders.Contains(Name)) {
Forwarded = false;
Forwarded = false;
}
}

Expand All @@ -67,28 +69,28 @@ public HeaderFieldInfo(string name, string value)

}

/// <summary>
/// Header name
/// <summary>
/// Header name
/// </summary>
[Key(0)]
public ReadOnlyMemory<char> Name { get; set; }

/// <summary>
/// Header value
/// <summary>
/// Header value
/// </summary>
[Key(1)]
public ReadOnlyMemory<char> Value { get; set; }

/// <summary>
/// <summary>
/// True if the header should be forwarded to the client or the server,
/// otherwise the header will be ignored by fluxzy (typically for connection related headers)
/// otherwise the header will be ignored by fluxzy (typically for connection related headers)
/// </summary>
[Key(2)]
public bool Forwarded { get; set; }

/// <summary>
/// Convenience method to convert this object to <see cref="HeaderField"/>
/// </summary>
/// <summary>
/// Convenience method to convert this object to <see cref="HeaderField"/>
/// </summary>
/// <param name="d"></param>
public static implicit operator HeaderFieldInfo(HeaderField d)
{
Expand Down
278 changes: 140 additions & 138 deletions src/Fluxzy.Core/Archiving/RequestHeaderInfo.cs
Original file line number Diff line number Diff line change
@@ -1,139 +1,141 @@
// Copyright 2021 - Haga Rakotoharivelo - https://github.com/haga-rak

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json.Serialization;
// Copyright 2021 - Haga Rakotoharivelo - https://github.com/haga-rak
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json.Serialization;
using Fluxzy.Core;
using MessagePack;

namespace Fluxzy
{
/// <summary>
/// This data structure is used for serialization only
/// </summary>
[MessagePackObject]
public class RequestHeaderInfo
{
protected bool Equals(RequestHeaderInfo other)
{
return Method.Span.Equals(other.Method.Span, StringComparison.Ordinal)
&& Scheme.Span.Equals(other.Scheme.Span, StringComparison.Ordinal)
&& Path.Span.Equals(other.Path.Span, StringComparison.Ordinal)
&& Authority.Span.Equals(other.Authority.Span, StringComparison.Ordinal)
&& Headers.SequenceEqual(other.Headers);
}

public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj))
return false;

if (ReferenceEquals(this, obj))
return true;

if (obj.GetType() != this.GetType())
return false;

return Equals((RequestHeaderInfo) obj);
}

public override int GetHashCode()
{
return HashCode.Combine(Method, Scheme, Path, Authority, Headers);
}

public RequestHeaderInfo(RequestHeader originalHeader, bool doNotForwardConnectionHeader = false)
{
Method = originalHeader.Method;
Scheme = originalHeader.Scheme;
Path = originalHeader.Path;
Authority = originalHeader.Authority;
Headers = originalHeader.HeaderFields.Select(s => new HeaderFieldInfo(s, doNotForwardConnectionHeader));
}

[JsonConstructor]
[SerializationConstructor]
public RequestHeaderInfo(
ReadOnlyMemory<char> method, ReadOnlyMemory<char> scheme, ReadOnlyMemory<char> path,
ReadOnlyMemory<char> authority, IEnumerable<HeaderFieldInfo> headers)
{
Method = method;
Scheme = scheme;
Path = path;
Authority = authority;
Headers = headers;
}

public RequestHeaderInfo(
string method, string scheme, string path,
string authority, IEnumerable<HeaderFieldInfo> headers)
: this (method.AsMemory(), scheme.AsMemory(), path.AsMemory(), authority.AsMemory(), headers)
{

}

public RequestHeaderInfo(
string method, string fullUrl, IEnumerable<HeaderFieldInfo> headers)
{
var uri = new Uri(fullUrl);

Method = method.AsMemory();
Scheme = uri.Scheme.AsMemory();
Path = uri.PathAndQuery.AsMemory();
Authority = uri.Authority.AsMemory();

var listHeaders = headers.ToList();

if (!listHeaders.Any(h => h.Name.Span.Equals(
":method".AsSpan(),
StringComparison.OrdinalIgnoreCase))) {

listHeaders.Add(new HeaderFieldInfo(":method".AsMemory(), Method, true));
listHeaders.Add(new HeaderFieldInfo(":authority".AsMemory(), Authority, true));
listHeaders.Add(new HeaderFieldInfo(":path".AsMemory(), Path, true));
listHeaders.Add(new HeaderFieldInfo(":scheme".AsMemory(), Scheme, true));
}

Headers = listHeaders;
}

[Key(0)]
public ReadOnlyMemory<char> Method { get; }

[Key(1)]
public ReadOnlyMemory<char> Scheme { get; }

[Key(2)]
public ReadOnlyMemory<char> Path { get; }

[Key(3)]
public ReadOnlyMemory<char> Authority { get; }

[Key(4)]
public IEnumerable<HeaderFieldInfo> Headers { get; }

public string GetFullUrl()
{
var stringPath = Path.ToString();

if (Uri.TryCreate(Path.ToString(), UriKind.Absolute, out var uri) &&
uri.Scheme.StartsWith("http", StringComparison.OrdinalIgnoreCase))
return stringPath;

return $"{Scheme}://{Authority}{stringPath}";
}

public string GetPathOnly()
{
var stringPath = Path.ToString();

if (Uri.TryCreate(Path.ToString(), UriKind.Absolute, out var uri) &&
uri.Scheme.StartsWith("http", StringComparison.OrdinalIgnoreCase))
return uri.PathAndQuery;

return $"{stringPath}";
}
}
}
using MessagePack;

namespace Fluxzy
{
/// <summary>
/// This data structure is used for serialization only
/// </summary>
[MessagePackObject]
public class RequestHeaderInfo
{
protected bool Equals(RequestHeaderInfo other)
{
return Method.Span.Equals(other.Method.Span, StringComparison.Ordinal)
&& Scheme.Span.Equals(other.Scheme.Span, StringComparison.Ordinal)
&& Path.Span.Equals(other.Path.Span, StringComparison.Ordinal)
&& Authority.Span.Equals(other.Authority.Span, StringComparison.Ordinal)
&& Headers.SequenceEqual(other.Headers);
}

public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj))
return false;

if (ReferenceEquals(this, obj))
return true;

if (obj.GetType() != this.GetType())
return false;

return Equals((RequestHeaderInfo) obj);
}

public override int GetHashCode()
{
return HashCode.Combine(Method, Scheme, Path, Authority, Headers);
}

public RequestHeaderInfo(RequestHeader originalHeader, bool doNotForwardConnectionHeader = false)
{
// Materialize pooled Memory<char> slices into string-backed memory
// to prevent use-after-free when the ExchangeScope returns the buffer to the pool
Method = originalHeader.Method.ToString().AsMemory();
Scheme = originalHeader.Scheme.ToString().AsMemory();
Path = originalHeader.Path.ToString().AsMemory();
Authority = originalHeader.Authority.ToString().AsMemory();
Headers = originalHeader.HeaderFields.Select(s => new HeaderFieldInfo(s, doNotForwardConnectionHeader)).ToList();
}

[JsonConstructor]
[SerializationConstructor]
public RequestHeaderInfo(
ReadOnlyMemory<char> method, ReadOnlyMemory<char> scheme, ReadOnlyMemory<char> path,
ReadOnlyMemory<char> authority, IEnumerable<HeaderFieldInfo> headers)
{
Method = method;
Scheme = scheme;
Path = path;
Authority = authority;
Headers = headers;
}

public RequestHeaderInfo(
string method, string scheme, string path,
string authority, IEnumerable<HeaderFieldInfo> headers)
: this (method.AsMemory(), scheme.AsMemory(), path.AsMemory(), authority.AsMemory(), headers)
{

}

public RequestHeaderInfo(
string method, string fullUrl, IEnumerable<HeaderFieldInfo> headers)
{
var uri = new Uri(fullUrl);

Method = method.AsMemory();
Scheme = uri.Scheme.AsMemory();
Path = uri.PathAndQuery.AsMemory();
Authority = uri.Authority.AsMemory();

var listHeaders = headers.ToList();

if (!listHeaders.Any(h => h.Name.Span.Equals(
":method".AsSpan(),
StringComparison.OrdinalIgnoreCase))) {

listHeaders.Add(new HeaderFieldInfo(":method".AsMemory(), Method, true));
listHeaders.Add(new HeaderFieldInfo(":authority".AsMemory(), Authority, true));
listHeaders.Add(new HeaderFieldInfo(":path".AsMemory(), Path, true));
listHeaders.Add(new HeaderFieldInfo(":scheme".AsMemory(), Scheme, true));
}

Headers = listHeaders;
}

[Key(0)]
public ReadOnlyMemory<char> Method { get; }

[Key(1)]
public ReadOnlyMemory<char> Scheme { get; }

[Key(2)]
public ReadOnlyMemory<char> Path { get; }

[Key(3)]
public ReadOnlyMemory<char> Authority { get; }

[Key(4)]
public IEnumerable<HeaderFieldInfo> Headers { get; }

public string GetFullUrl()
{
var stringPath = Path.ToString();

if (Uri.TryCreate(Path.ToString(), UriKind.Absolute, out var uri) &&
uri.Scheme.StartsWith("http", StringComparison.OrdinalIgnoreCase))
return stringPath;

return $"{Scheme}://{Authority}{stringPath}";
}

public string GetPathOnly()
{
var stringPath = Path.ToString();

if (Uri.TryCreate(Path.ToString(), UriKind.Absolute, out var uri) &&
uri.Scheme.StartsWith("http", StringComparison.OrdinalIgnoreCase))
return uri.PathAndQuery;

return $"{stringPath}";
}
}
}
4 changes: 2 additions & 2 deletions src/Fluxzy.Core/Archiving/ResponseHeaderInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using Fluxzy.Core;
using Fluxzy.Core;
using MessagePack;

namespace Fluxzy
Expand Down Expand Up @@ -67,7 +67,7 @@ public ResponseHeaderInfo(int statusCode, IEnumerable<HeaderFieldInfo> headers,
public ResponseHeaderInfo(ResponseHeader originalHeader, bool doNotForwardConnectionHeader = false)
{
StatusCode = originalHeader.StatusCode;
Headers = originalHeader.HeaderFields.Select(s => new HeaderFieldInfo(s, doNotForwardConnectionHeader));
Headers = originalHeader.HeaderFields.Select(s => new HeaderFieldInfo(s, doNotForwardConnectionHeader)).ToList();
}

[Key(0)]
Expand Down
Loading