Added IPv6 toString implementation.
This commit is contained in:
parent
9a4c4a46f6
commit
79e6912b56
|
@ -14,3 +14,4 @@ handy-http-primitives-test-*
|
|||
*.o
|
||||
*.obj
|
||||
*.lst
|
||||
*.a
|
||||
|
|
2
dub.json
2
dub.json
|
@ -7,6 +7,6 @@
|
|||
"streams": "~>3.5.0"
|
||||
},
|
||||
"description": "Basic HTTP types that can be shared among various projects.",
|
||||
"license": "MIT",
|
||||
"license": "CC0",
|
||||
"name": "handy-http-primitives"
|
||||
}
|
|
@ -10,18 +10,6 @@ module handy_http_primitives.address;
|
|||
struct IPv4InternetAddress {
|
||||
const ubyte[4] bytes;
|
||||
const ushort port;
|
||||
|
||||
string toString() const {
|
||||
char[21] buffer;
|
||||
size_t idx;
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
writeUIntToBuffer(bytes[i], buffer, idx);
|
||||
if (i < 3) buffer[idx++] = '.';
|
||||
}
|
||||
buffer[idx++] = ':';
|
||||
writeUIntToBuffer(port, buffer, idx);
|
||||
return buffer[0 .. idx].idup;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,10 +19,6 @@ struct IPv4InternetAddress {
|
|||
struct IPv6InternetAddress {
|
||||
const ubyte[16] bytes;
|
||||
const ushort port;
|
||||
|
||||
string toString() const {
|
||||
return "Not implemented!";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -43,10 +27,6 @@ struct IPv6InternetAddress {
|
|||
*/
|
||||
struct UnixSocketAddress {
|
||||
const string path;
|
||||
|
||||
string toString() const {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines the different possible address types, used by `ClientAddress`.
|
||||
|
@ -66,14 +46,33 @@ struct ClientAddress {
|
|||
const IPv6InternetAddress ipv6InternetAddress;
|
||||
const UnixSocketAddress unixSocketAddress;
|
||||
|
||||
/**
|
||||
* Serializes this address in a human-readable string representation.
|
||||
* Returns: The string representation of this address.
|
||||
*/
|
||||
string toString() const {
|
||||
if (type == ClientAddressType.IPv4) {
|
||||
return ipv4InternetAddress.toString();
|
||||
} else if (type == ClientAddressType.IPv6) {
|
||||
return ipv6InternetAddress.toString();
|
||||
} else {
|
||||
return unixSocketAddress.toString();
|
||||
if (type == ClientAddressType.UNIX) return unixSocketAddress.path;
|
||||
version (Posix) { import core.sys.posix.arpa.inet : inet_ntop, AF_INET, AF_INET6; }
|
||||
version (Windows) { import core.sys.windows.winsock2 : inet_ntop, AF_INET, AF_INET6; }
|
||||
const int addressFamily = type == ClientAddressType.IPv4
|
||||
? AF_INET
|
||||
:AF_INET6;
|
||||
const scope void* inputBytes = type == ClientAddressType.IPv4
|
||||
? ipv4InternetAddress.bytes.ptr
|
||||
: ipv6InternetAddress.bytes.ptr;
|
||||
const ushort port = type == ClientAddressType.IPv4
|
||||
? ipv4InternetAddress.port
|
||||
: ipv6InternetAddress.port;
|
||||
char[45] buf; // Buffer is sized to maximum possible IPv6 length (39 chars), plus 6 chars for port string.
|
||||
auto ret = inet_ntop(addressFamily, inputBytes, buf.ptr, buf.length);
|
||||
if (ret is null) {
|
||||
throw new Exception("Failed to serialize address.");
|
||||
}
|
||||
size_t strLength = 0;
|
||||
while (buf[strLength] != '\0') strLength++;
|
||||
buf[strLength++] = ':';
|
||||
writeUIntToBuffer(port, buf, strLength);
|
||||
return buf[0..strLength].idup;
|
||||
}
|
||||
|
||||
static ClientAddress ofIPv4(IPv4InternetAddress addr) {
|
||||
|
@ -92,6 +91,12 @@ struct ClientAddress {
|
|||
unittest {
|
||||
ClientAddress addr = ClientAddress.ofIPv4(IPv4InternetAddress([127, 0, 0, 1], 8000));
|
||||
assert(addr.toString == "127.0.0.1:8000");
|
||||
ClientAddress addr6 = ClientAddress.ofIPv6(IPv6InternetAddress(
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
8000
|
||||
));
|
||||
assert(addr6.toString == ":::8000");
|
||||
// TODO: Add more comprehensive testing.
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,7 +3,6 @@ module handy_http_primitives.request;
|
|||
import streams : InputStream;
|
||||
import std.traits : EnumMembers;
|
||||
|
||||
import handy_http_primitives.multivalue_map;
|
||||
import handy_http_primitives.optional;
|
||||
import handy_http_primitives.address;
|
||||
|
||||
|
@ -21,7 +20,7 @@ struct ServerHttpRequest {
|
|||
/// The URL that was requested.
|
||||
const string url = "";
|
||||
/// A case-insensitive map of all request headers.
|
||||
const(CaseInsensitiveStringMultiValueMap) headers;
|
||||
const(string[][string]) headers;
|
||||
/// The underlying stream used to read the body from the request.
|
||||
InputStream!ubyte inputStream;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ struct ServerHttpResponse {
|
|||
* A struct containing basic information about a response status.
|
||||
*/
|
||||
struct StatusInfo {
|
||||
const ushort code;
|
||||
const string text;
|
||||
ushort code;
|
||||
string text;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,3 +101,13 @@ enum HttpStatus : StatusInfo {
|
|||
NOT_EXTENDED = StatusInfo(510, "Not Extended"),
|
||||
NETWORK_AUTHENTICATION_REQUIRED = StatusInfo(511, "Network Authentication Required")
|
||||
}
|
||||
|
||||
/// Common "Content-Type" header values.
|
||||
enum ContentTypes : string {
|
||||
APPLICATION_JSON = "application/json",
|
||||
APPLICATION_XML = "application/xml",
|
||||
|
||||
TEXT_PLAIN = "text/plain",
|
||||
TEXT_HTML = "text/html",
|
||||
TEXT_CSS = "text/css"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue