Addressed issues #3 (client address) and #1 (HTTP methods as strings)

This commit is contained in:
Andrew Lalis 2024-10-28 10:12:03 -04:00
parent 23c74f82be
commit 082a4ba42c
1 changed files with 40 additions and 17 deletions

View File

@ -13,10 +13,12 @@ import handy_http_primitives.optional;
struct ServerHttpRequest { struct ServerHttpRequest {
/// The HTTP version of the request. /// The HTTP version of the request.
const HttpVersion httpVersion = HttpVersion.V1_1; const HttpVersion httpVersion = HttpVersion.V1_1;
/// The remote address of the client that sent this request.
const InternetAddress clientAddress;
/// The HTTP verb used in the request. /// The HTTP verb used in the request.
const HttpMethod method = HttpMethod.GET; const string method = HttpMethod.GET;
/// The URL that was requested. /// The URL that was requested.
const(char[]) url = ""; const string url = "";
/// A case-insensitive map of all request headers. /// A case-insensitive map of all request headers.
const(CaseInsensitiveStringMultiValueMap) headers; const(CaseInsensitiveStringMultiValueMap) headers;
/// A case-sensitive map of all URL query parameters. /// A case-sensitive map of all URL query parameters.
@ -36,21 +38,20 @@ public enum HttpVersion : ubyte {
} }
/** /**
* Enumeration of all possible HTTP request methods as unsigned integer values * Enumeration of all possible HTTP methods, excluding extensions like WebDAV.
* for efficient logic.
* *
* https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods * https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
*/ */
public enum HttpMethod : ushort { public enum HttpMethod : string {
GET = 1 << 0, GET = "GET",
HEAD = 1 << 1, HEAD = "HEAD",
POST = 1 << 2, POST = "POST",
PUT = 1 << 3, PUT = "PUT",
DELETE = 1 << 4, DELETE = "DELETE",
CONNECT = 1 << 5, CONNECT = "CONNECT",
OPTIONS = 1 << 6, OPTIONS = "OPTIONS",
TRACE = 1 << 7, TRACE = "TRACE",
PATCH = 1 << 8 PATCH = "PATCH"
} }
/** /**
@ -62,13 +63,12 @@ public enum HttpMethod : ushort {
Optional!HttpMethod parseHttpMethod(S)(S s) if (isSomeString!S) { Optional!HttpMethod parseHttpMethod(S)(S s) if (isSomeString!S) {
import std.uni : toUpper; import std.uni : toUpper;
import std.string : strip; import std.string : strip;
import std.conv : to;
static foreach (m; EnumMembers!HttpMethod) { static foreach (m; EnumMembers!HttpMethod) {
if (s == to!string(m)) return Optional!HttpMethod.of(m); if (s == m) return Optional!HttpMethod.of(m);
} }
const cleanStr = strip(toUpper(s)); const cleanStr = strip(toUpper(s));
static foreach (m; EnumMembers!HttpMethod) { static foreach (m; EnumMembers!HttpMethod) {
if (cleanStr == to!string(m)) return Optional!HttpMethod.of(m); if (cleanStr == m) return Optional!HttpMethod.of(m);
} }
return Optional!HttpMethod.empty; return Optional!HttpMethod.empty;
} }
@ -82,3 +82,26 @@ unittest {
assert(parseHttpMethod(" not a method!") == R.empty); assert(parseHttpMethod(" not a method!") == R.empty);
assert(parseHttpMethod("") == R.empty); assert(parseHttpMethod("") == R.empty);
} }
/// The data representing a remote IPv4 internet address, available as an int or bytes.
union IPv4InternetAddress {
const uint intValue;
const ubyte[4] bytes;
}
/// The data representing a remote IPv6 internet address.
struct IPv6InternetAddress {
const ubyte[16] bytes;
}
/// A remote internet address, which is either IPv4 or IPv6. Check `isIPv6`.
struct InternetAddress {
/// True if this address is IPv6. False if this is an IPv4 address.
const bool isIPv6;
/// The port number assigned to the connecting client on this machine.
const ushort port;
union {
IPv4InternetAddress ipv4Address;
IPv6InternetAddress ipv6Address;
}
}