Add PhotonHttp1Transport implementation.
This commit is contained in:
parent
7ff80c8a9f
commit
8862aab12e
5
dub.json
5
dub.json
|
@ -5,8 +5,9 @@
|
||||||
"copyright": "Copyright © 2024, Andrew Lalis",
|
"copyright": "Copyright © 2024, Andrew Lalis",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"handy-http-primitives": "~>1.8",
|
"handy-http-primitives": "~>1.8",
|
||||||
"streams": "~>3.6",
|
"photon": "~>0.15.0",
|
||||||
"slf4d": "~>4.0"
|
"slf4d": "~>4.0",
|
||||||
|
"streams": "~>3.6"
|
||||||
},
|
},
|
||||||
"description": "Implementations of HTTP transport protocols.",
|
"description": "Implementations of HTTP transport protocols.",
|
||||||
"license": "CC0",
|
"license": "CC0",
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
"fileVersion": 1,
|
"fileVersion": 1,
|
||||||
"versions": {
|
"versions": {
|
||||||
"handy-http-primitives": "1.8.0",
|
"handy-http-primitives": "1.8.0",
|
||||||
|
"photon": "0.15.0",
|
||||||
|
"sharded-map": "2.7.0",
|
||||||
"slf4d": "4.1.1",
|
"slf4d": "4.1.1",
|
||||||
"streams": "3.6.0"
|
"streams": "3.6.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
module handy_http_transport.http1.photon;
|
||||||
|
|
||||||
|
import handy_http_transport.http1.transport;
|
||||||
|
import handy_http_primitives;
|
||||||
|
import slf4d;
|
||||||
|
|
||||||
|
import photon;
|
||||||
|
import std.socket;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of Http1Transport which uses Dimitry Olshansky's Photon
|
||||||
|
* library for asynchronous task processing. A main fiber is started which
|
||||||
|
* accepts incoming client sockets, and a fiber is spawned for each client so
|
||||||
|
* its request can be handled asynchronously.
|
||||||
|
*/
|
||||||
|
class PhotonHttp1Transport : Http1Transport {
|
||||||
|
this(HttpRequestHandler handler, ushort port = 8080) {
|
||||||
|
super(handler, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
override void runServer() {
|
||||||
|
initPhoton();
|
||||||
|
go(() {
|
||||||
|
Socket serverSocket = new TcpSocket();
|
||||||
|
serverSocket.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, 1);
|
||||||
|
serverSocket.bind(parseAddress("127.0.0.1", port));
|
||||||
|
debugF!"Bound the server socket to %s"(serverSocket.localAddress);
|
||||||
|
serverSocket.listen(1024);
|
||||||
|
debug_("Server is now listening.");
|
||||||
|
|
||||||
|
while (super.isRunning) {
|
||||||
|
try {
|
||||||
|
trace("Waiting to accept a new socket.");
|
||||||
|
Socket clientSocket = serverSocket.accept();
|
||||||
|
trace("Accepted a new socket.");
|
||||||
|
go(() => handleClient(clientSocket, requestHandler));
|
||||||
|
trace("Added handleClient() task to the task pool.");
|
||||||
|
} catch (SocketAcceptException e) {
|
||||||
|
warn("Failed to accept socket connection.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
serverSocket.close();
|
||||||
|
});
|
||||||
|
runScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
override void stop() {
|
||||||
|
super.stop();
|
||||||
|
// Send a dummy request to cause the server's blocking accept() call to end.
|
||||||
|
try {
|
||||||
|
Socket dummySocket = new TcpSocket(new InternetAddress("127.0.0.1", port));
|
||||||
|
dummySocket.shutdown(SocketShutdown.BOTH);
|
||||||
|
dummySocket.close();
|
||||||
|
} catch (SocketOSException e) {
|
||||||
|
warn("Failed to send empty request to stop server.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest {
|
||||||
|
testHttp1Transport(new PhotonHttp1Transport(
|
||||||
|
HttpRequestHandler.of((req, resp) {
|
||||||
|
resp.status = HttpStatus.OK;
|
||||||
|
}),
|
||||||
|
8080
|
||||||
|
));
|
||||||
|
}
|
|
@ -59,6 +59,11 @@ version(unittest) {
|
||||||
void testHttp1Transport(Http1Transport transport) {
|
void testHttp1Transport(Http1Transport transport) {
|
||||||
import core.thread;
|
import core.thread;
|
||||||
import std.string;
|
import std.string;
|
||||||
|
|
||||||
|
import slf4d.default_provider;
|
||||||
|
auto loggingProvider = new DefaultProvider(Levels.DEBUG);
|
||||||
|
configureLoggingProvider(loggingProvider);
|
||||||
|
|
||||||
infoF!"Testing Http1Transport implementation: %s"(transport);
|
infoF!"Testing Http1Transport implementation: %s"(transport);
|
||||||
|
|
||||||
Thread thread = transport.startInNewThread();
|
Thread thread = transport.startInNewThread();
|
||||||
|
@ -102,6 +107,8 @@ version(unittest) {
|
||||||
info("Testing is complete. Stopping the server.");
|
info("Testing is complete. Stopping the server.");
|
||||||
transport.stop();
|
transport.stop();
|
||||||
thread.join();
|
thread.join();
|
||||||
|
|
||||||
|
resetLoggingState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue