Uwaa/HTTP/HttpResponse.cs

114 lines
3.4 KiB
C#
Raw Normal View History

2024-11-22 07:40:43 +01:00
using System.Text;
using Uwaa.HTTP.Websockets;
namespace Uwaa.HTTP;
public class SwitchingProtocols : HttpResponse
{
/// <summary>
/// Called once a HTTP request is upgrade to a websocket.
/// </summary>
public readonly WebsocketHandler Callback;
internal SwitchingProtocols(string acceptKey, string? chosenProtocol, WebsocketHandler callback) : base(101, "Switching Protocols", new HttpFields())
{
Fields.WebSocketAccept = acceptKey;
Fields.WebSocketProtocol = chosenProtocol;
Fields.Upgrade = "websocket";
Fields.Connection = ConnectionType.Upgrade;
Callback = callback;
}
}
/// <summary>
/// Contains the status code, status message, fields, and content of a HTTP response.
/// </summary>
public class HttpResponse
{
2024-11-24 08:46:13 +01:00
public static HttpResponse OK(HttpContent? content = null) => new HttpResponse(200, "OK", content);
2024-11-22 07:40:43 +01:00
public static HttpResponse Redirect(string location) => new HttpResponse(301, "Redirect", new HttpFields() { Location = location });
2024-11-24 08:46:13 +01:00
public static HttpResponse BadRequest(HttpContent? content = null) => new HttpResponse(400, "Bad request", content);
2024-11-22 07:40:43 +01:00
2024-11-24 08:46:13 +01:00
public static HttpResponse NotFound(HttpContent? content = null) => new HttpResponse(404, "Not found", content);
2024-11-22 07:40:43 +01:00
2024-11-24 08:46:13 +01:00
public static HttpResponse NotAcceptable(HttpContent? content = null) => new HttpResponse(406, "Not acceptable", content);
2024-11-22 07:40:43 +01:00
2024-11-24 08:46:13 +01:00
public static HttpResponse InternalServerError(HttpContent? content = null) => new HttpResponse(500, "Internal server error", content);
public static implicit operator HttpResponse(HttpContent value) => OK(value);
public static implicit operator HttpResponse(HttpContent? value) => value == null ? NotFound(value) : OK(value);
2024-11-22 07:40:43 +01:00
public readonly int StatusCode;
public readonly string StatusMessage;
/// <summary>
/// HTTP header fields included in the response.
/// </summary>
public readonly HttpFields Fields;
/// <summary>
/// The body of the HTTP body, if any.
/// </summary>
public readonly HttpContent? Content;
public HttpResponse(int statusCode, string statusMessage, HttpContent? body = null) : this(statusCode, statusMessage, new HttpFields(), body)
{
}
public HttpResponse(int statusCode, string statusMessage, HttpFields fields, HttpContent? body = null)
{
StatusCode = statusCode;
StatusMessage = statusMessage;
Fields = fields;
Content = body;
}
internal async Task WriteTo(HttpStream stream)
{
if (StatusCode == 0)
return;
StringBuilder sb = new StringBuilder();
void writeField(string name, string value)
{
sb.Append(name);
sb.Append(": ");
sb.Append(value);
sb.Append("\r\n");
}
sb.Append("HTTP/1.1 ");
sb.Append(StatusCode);
sb.Append(' ');
sb.Append(StatusMessage);
sb.Append("\r\n");
if (Content.HasValue)
{
Fields.ContentLength = Content.Value.Content.Length;
Fields.ContentType = Content.Value.Type.ToString();
}
else
{
Fields.ContentLength = null;
Fields.ContentType = null;
}
Fields.EmitAll(writeField);
sb.Append("\r\n");
await stream.Write(Encoding.ASCII.GetBytes(sb.ToString()));
if (Content.HasValue)
await stream.Write(Content.Value.Content);
await stream.Flush();
}
2024-11-24 08:45:54 +01:00
}