183 lines
No EOL
5.1 KiB
C#
183 lines
No EOL
5.1 KiB
C#
namespace Uwaa.HTTP;
|
|
|
|
/// <summary>
|
|
/// General purpose implementation of <see cref="IHttpFields"/>.
|
|
/// </summary>
|
|
public record HttpFields
|
|
{
|
|
public MIMEType[]? Accept { get; set; }
|
|
|
|
public ConnectionType? Connection { get; set; }
|
|
|
|
public string? Host { get; set; }
|
|
|
|
public string? Upgrade { get; set; }
|
|
|
|
public string? UserAgent { get; set; }
|
|
|
|
public string? Authorization { get; set; }
|
|
|
|
public string? WebSocketKey { get; set; }
|
|
|
|
public string? WebSocketAccept { get; set; }
|
|
|
|
public string? WebSocketProtocol { get; set; }
|
|
|
|
public string? Location { get; set; }
|
|
|
|
public int? ContentLength { get; set; }
|
|
|
|
public MIMEType? ContentType { get; set; }
|
|
|
|
/// <summary>
|
|
/// Extra fields to include.
|
|
/// </summary>
|
|
public Dictionary<string, string>? Misc;
|
|
|
|
/// <summary>
|
|
/// Sets a field. The string will be parsed for non-string fields like Accept.
|
|
/// </summary>
|
|
public virtual string? this[string key]
|
|
{
|
|
set
|
|
{
|
|
switch (key.ToLowerInvariant())
|
|
{
|
|
case "accept":
|
|
Accept = value == null ? null : HttpHelpers.ParseAccept(value);
|
|
return;
|
|
|
|
case "connection":
|
|
{
|
|
if (Enum.TryParse(value, true, out ConnectionType conType))
|
|
Connection = conType;
|
|
return;
|
|
}
|
|
|
|
case "host":
|
|
Host = value;
|
|
return;
|
|
|
|
case "upgrade":
|
|
Upgrade = value;
|
|
return;
|
|
|
|
case "user-agent":
|
|
UserAgent = value;
|
|
return;
|
|
|
|
case "authorization":
|
|
Authorization = value;
|
|
return;
|
|
|
|
case "sec-websocket-key":
|
|
WebSocketKey = value;
|
|
return;
|
|
|
|
case "sec-websocket-accept":
|
|
WebSocketAccept = value;
|
|
return;
|
|
|
|
case "sec-websocket-protocol":
|
|
WebSocketProtocol = value;
|
|
return;
|
|
|
|
case "location":
|
|
Location = value;
|
|
return;
|
|
|
|
case "content-length":
|
|
{
|
|
if (value == null)
|
|
{
|
|
ContentLength = 0;
|
|
}
|
|
else
|
|
{
|
|
if (!int.TryParse(value, out int contentLength))
|
|
throw new HttpException("Invalid Content-Length");
|
|
ContentLength = contentLength;
|
|
}
|
|
return;
|
|
}
|
|
|
|
case "content-type":
|
|
ContentType = value == null ? (MIMEType?)null: new MIMEType(value);
|
|
return;
|
|
|
|
default:
|
|
if (value == null)
|
|
{
|
|
Misc?.Remove(key);
|
|
}
|
|
else
|
|
{
|
|
Misc ??= new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
Misc[key] = value;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generates strings for the fields and sends them to the provided callback.
|
|
/// </summary>
|
|
public virtual void EmitAll(FieldCallback callback)
|
|
{
|
|
if (ContentLength.HasValue)
|
|
callback("Content-Length", ContentLength.Value.ToString());
|
|
|
|
if (ContentType.HasValue)
|
|
callback("Content-Type", ContentType.Value.ToString());
|
|
|
|
if (Accept != null)
|
|
callback("Accept", string.Join(", ", Accept));
|
|
|
|
if (Connection.HasValue)
|
|
callback("Connection", Connection.Value switch
|
|
{
|
|
ConnectionType.Close => "close",
|
|
ConnectionType.KeepAlive => "keepalive",
|
|
ConnectionType.Upgrade => "upgrade",
|
|
_ => "close",
|
|
});
|
|
|
|
if (Host != null)
|
|
callback("Host", Host);
|
|
|
|
if (UserAgent != null)
|
|
callback("User-Agent", UserAgent);
|
|
|
|
if (Authorization != null)
|
|
callback("Authorization", Authorization);
|
|
|
|
if (Upgrade != null)
|
|
callback("Upgrade", Upgrade);
|
|
|
|
if (Location != null)
|
|
callback("Location", Location);
|
|
|
|
if (WebSocketKey != null)
|
|
callback("Sec-WebSocket-Key", WebSocketKey);
|
|
|
|
if (WebSocketAccept != null)
|
|
callback("Sec-WebSocket-Accept", WebSocketAccept);
|
|
|
|
if (WebSocketProtocol != null)
|
|
callback("Sec-WebSocket-Protocol", WebSocketProtocol);
|
|
|
|
if (Misc != null)
|
|
foreach (var pair in Misc)
|
|
callback(pair.Key, pair.Value);
|
|
}
|
|
}
|
|
|
|
public delegate void FieldCallback(string name, string value);
|
|
|
|
public enum ConnectionType
|
|
{
|
|
Close,
|
|
KeepAlive,
|
|
Upgrade,
|
|
} |