Compare commits
No commits in common. "main" and "v1.5.0" have entirely different histories.
|
@ -8,8 +8,8 @@ module handy_http_primitives.address;
|
||||||
* that the connection was assigned to.
|
* that the connection was assigned to.
|
||||||
*/
|
*/
|
||||||
struct IPv4InternetAddress {
|
struct IPv4InternetAddress {
|
||||||
ubyte[4] bytes;
|
const ubyte[4] bytes;
|
||||||
ushort port;
|
const ushort port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,8 +17,8 @@ struct IPv4InternetAddress {
|
||||||
* machine that the connection was assigned to.
|
* machine that the connection was assigned to.
|
||||||
*/
|
*/
|
||||||
struct IPv6InternetAddress {
|
struct IPv6InternetAddress {
|
||||||
ubyte[16] bytes;
|
const ubyte[16] bytes;
|
||||||
ushort port;
|
const ushort port;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,7 +26,7 @@ struct IPv6InternetAddress {
|
||||||
* IO operations take place.
|
* IO operations take place.
|
||||||
*/
|
*/
|
||||||
struct UnixSocketAddress {
|
struct UnixSocketAddress {
|
||||||
string path;
|
const string path;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Defines the different possible address types, used by `ClientAddress`.
|
/// Defines the different possible address types, used by `ClientAddress`.
|
||||||
|
@ -42,10 +42,10 @@ enum ClientAddressType {
|
||||||
* request. Use `type` to determine which information is available.
|
* request. Use `type` to determine which information is available.
|
||||||
*/
|
*/
|
||||||
struct ClientAddress {
|
struct ClientAddress {
|
||||||
ClientAddressType type;
|
const ClientAddressType type;
|
||||||
IPv4InternetAddress ipv4InternetAddress;
|
const IPv4InternetAddress ipv4InternetAddress;
|
||||||
IPv6InternetAddress ipv6InternetAddress;
|
const IPv6InternetAddress ipv6InternetAddress;
|
||||||
UnixSocketAddress unixSocketAddress;
|
const UnixSocketAddress unixSocketAddress;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serializes this address in a human-readable string representation.
|
* Serializes this address in a human-readable string representation.
|
||||||
|
|
|
@ -1,158 +0,0 @@
|
||||||
/**
|
|
||||||
* Defines builder types to more easily construct various HTTP objects, often
|
|
||||||
* useful for testing scenarios.
|
|
||||||
*/
|
|
||||||
module handy_http_primitives.builder;
|
|
||||||
|
|
||||||
import streams;
|
|
||||||
|
|
||||||
import handy_http_primitives.request;
|
|
||||||
import handy_http_primitives.response;
|
|
||||||
import handy_http_primitives.address;
|
|
||||||
import handy_http_primitives.multivalue_map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fluent interface for building ServerHttpRequest objects.
|
|
||||||
*/
|
|
||||||
struct ServerHttpRequestBuilder {
|
|
||||||
HttpVersion httpVersion = HttpVersion.V1;
|
|
||||||
ClientAddress clientAddress = ClientAddress.unknown;
|
|
||||||
string method = HttpMethod.GET;
|
|
||||||
string url = "";
|
|
||||||
string[][string] headers;
|
|
||||||
QueryParameter[] queryParams;
|
|
||||||
InputStream!ubyte inputStream = inputStreamObjectFor(NoOpInputStream!ubyte());
|
|
||||||
|
|
||||||
ref withVersion(HttpVersion httpVersion) {
|
|
||||||
this.httpVersion = httpVersion;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withClientAddress(ClientAddress addr) {
|
|
||||||
this.clientAddress = addr;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withMethod(string method) {
|
|
||||||
this.method = method;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withUrl(string url) {
|
|
||||||
this.url = url;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withHeader(string headerName, string value) {
|
|
||||||
if (headerName !in this.headers) {
|
|
||||||
this.headers[headerName] = [];
|
|
||||||
}
|
|
||||||
this.headers[headerName] ~= value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withQueryParam(string paramName, string value) {
|
|
||||||
foreach (ref param; this.queryParams) {
|
|
||||||
if (param.key == paramName) {
|
|
||||||
param.values ~= value;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.queryParams ~= QueryParameter(paramName, [value]);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withInputStream(S)(S stream) if (isByteInputStream!S) {
|
|
||||||
this.inputStream = inputStreamObjectFor(stream);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withBody(ubyte[] bodyBytes) {
|
|
||||||
return withInputStream(arrayInputStreamFor(bodyBytes));
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withBody(string bodyStr) {
|
|
||||||
return withBody(cast(ubyte[]) bodyStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerHttpRequest build() {
|
|
||||||
return ServerHttpRequest(
|
|
||||||
httpVersion,
|
|
||||||
clientAddress,
|
|
||||||
method,
|
|
||||||
url,
|
|
||||||
headers,
|
|
||||||
queryParams,
|
|
||||||
inputStream
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest {
|
|
||||||
ServerHttpRequest r1 = ServerHttpRequestBuilder()
|
|
||||||
.withUrl("/test-url")
|
|
||||||
.withVersion(HttpVersion.V2)
|
|
||||||
.withMethod(HttpMethod.PATCH)
|
|
||||||
.withBody("Hello world!")
|
|
||||||
.withClientAddress(ClientAddress.ofUnixSocket(UnixSocketAddress("/tmp/socket")))
|
|
||||||
.withHeader("Content-Type", "text/plain")
|
|
||||||
.withHeader("Content-Length", "12")
|
|
||||||
.withQueryParam("idx", "42")
|
|
||||||
.build();
|
|
||||||
assert(r1.httpVersion == HttpVersion.V2);
|
|
||||||
assert(r1.url == "/test-url");
|
|
||||||
assert(r1.method == HttpMethod.PATCH);
|
|
||||||
string r1Body = r1.readBodyAsString();
|
|
||||||
assert(r1Body == "Hello world!");
|
|
||||||
assert(r1.clientAddress.type == ClientAddressType.UNIX);
|
|
||||||
assert(r1.clientAddress.unixSocketAddress.path == "/tmp/socket");
|
|
||||||
assert(r1.getHeaderAs!string("Content-Type") == "text/plain");
|
|
||||||
assert(r1.getHeaderAs!ulong("Content-Length") == 12);
|
|
||||||
assert(r1.getParamAs!ulong("idx") == 42);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fluent interface for building ServerHttpResponse objects.
|
|
||||||
*/
|
|
||||||
struct ServerHttpResponseBuilder {
|
|
||||||
StatusInfo initialStatus = HttpStatus.OK;
|
|
||||||
StringMultiValueMap initialHeaders;
|
|
||||||
OutputStream!ubyte outputStream = outputStreamObjectFor(NoOpOutputStream!ubyte());
|
|
||||||
|
|
||||||
ref withStatus(StatusInfo status) {
|
|
||||||
this.initialStatus = status;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withHeader(string headerName, string value) {
|
|
||||||
this.initialHeaders.add(headerName, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref withOutputStream(S)(S stream) if (isByteOutputStream!S) {
|
|
||||||
this.outputStream = outputStreamObjectFor(stream);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServerHttpResponse build() {
|
|
||||||
return ServerHttpResponse(
|
|
||||||
initialStatus,
|
|
||||||
initialHeaders,
|
|
||||||
outputStream
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest {
|
|
||||||
ArrayOutputStream!ubyte bufferOut = byteArrayOutputStream();
|
|
||||||
ServerHttpResponse r1 = ServerHttpResponseBuilder()
|
|
||||||
.withStatus(HttpStatus.BAD_REQUEST)
|
|
||||||
.withHeader("Test", "okay")
|
|
||||||
.withOutputStream(&bufferOut)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
assert(r1.status == HttpStatus.BAD_REQUEST);
|
|
||||||
assert(r1.headers.getFirst("Test").value == "okay");
|
|
||||||
r1.outputStream.writeToStream(cast(ubyte[]) "Hello world!");
|
|
||||||
assert(bufferOut.toArray() == cast(ubyte[]) "Hello world!");
|
|
||||||
}
|
|
|
@ -5,4 +5,3 @@ public import handy_http_primitives.response;
|
||||||
public import handy_http_primitives.handler;
|
public import handy_http_primitives.handler;
|
||||||
public import handy_http_primitives.optional;
|
public import handy_http_primitives.optional;
|
||||||
public import handy_http_primitives.multivalue_map;
|
public import handy_http_primitives.multivalue_map;
|
||||||
public import handy_http_primitives.builder;
|
|
||||||
|
|
Loading…
Reference in New Issue