Skip to content

Commit 69d7cb3

Browse files
committed
Add server support for Unix sockets.
Allows to pass the absolute socket path as the bind address string. Closes vibe-d/vibe.d#2073.
1 parent 9f1de28 commit 69d7cb3

File tree

3 files changed

+73
-5
lines changed

3 files changed

+73
-5
lines changed

source/vibe/http/server.d

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ else version (Have_botan) enum HaveNoTLS = false;
5252
else version (Have_openssl) enum HaveNoTLS = false;
5353
else enum HaveNoTLS = true;
5454

55+
version(Posix)
56+
{
57+
version = UnixSocket;
58+
}
59+
60+
5561
/**************************************************************************************************/
5662
/* Public functions */
5763
/**************************************************************************************************/
@@ -1923,7 +1929,30 @@ private HTTPListener listenHTTPPlain(HTTPServerSettings settings, HTTPServerRequ
19231929
TCPListenOptions options = TCPListenOptions.defaults;
19241930
if(reuseAddress) options |= TCPListenOptions.reuseAddress; else options &= ~TCPListenOptions.reuseAddress;
19251931
if(reusePort) options |= TCPListenOptions.reusePort; else options &= ~TCPListenOptions.reusePort;
1926-
auto ret = listenTCP(listen_info.bindPort, (TCPConnection conn) nothrow @safe {
1932+
1933+
NetworkAddress bind_address;
1934+
1935+
auto proto = is_tls ? "https" : "http";
1936+
1937+
if (listen_info.bindAddress.startsWith("/")) {
1938+
version (UnixSocket) {
1939+
import std.socket : AddressFamily;
1940+
import core.sys.posix.sys.un : sockaddr_un;
1941+
import core.stdc.string : strcpy;
1942+
1943+
bind_address.family = AddressFamily.UNIX;
1944+
sockaddr_un* s = bind_address.sockAddrUnix();
1945+
enforce(s.sun_path.length > listen_info.bindAddress.length, "Unix sockets cannot have that long a name.");
1946+
s.sun_family = AddressFamily.UNIX;
1947+
() @trusted { strcpy(cast(char*)s.sun_path.ptr, listen_info.bindAddress.toStringz()); } ();
1948+
proto ~= "+unix";
1949+
} else throw new Exception("Unix domain sockets are not supported on this platform.");
1950+
} else {
1951+
bind_address = resolveHost(listen_info.bindAddress);
1952+
bind_address.port = listen_info.bindPort;
1953+
}
1954+
1955+
auto ret = listenTCP((TCPConnection conn) nothrow @safe {
19271956
auto raddr = conn.remoteAddress;
19281957
try handleHTTPConnection(conn, listen_info, raddr);
19291958
catch (Exception e) {
@@ -1932,16 +1961,18 @@ private HTTPListener listenHTTPPlain(HTTPServerSettings settings, HTTPServerRequ
19321961
try conn.close();
19331962
catch (Exception e) logError("Failed to close connection: %s", e.msg);
19341963
}
1935-
}, listen_info.bindAddress, options);
1964+
}, bind_address, options);
19361965

19371966
// support port 0 meaning any available port
1938-
if (listen_info.bindPort == 0)
1967+
if (listen_info.bindPort == 0) {
19391968
listen_info.m_bindPort = ret.bindAddress.port;
1969+
bind_address.port = ret.bindAddress.port;
1970+
}
19401971

1941-
auto proto = is_tls ? "https" : "http";
19421972
auto urladdr = listen_info.bindAddress;
19431973
if (urladdr.canFind(':')) urladdr = "["~urladdr~"]";
1944-
logInfo("Listening for requests on %s://%s:%s/", proto, urladdr, listen_info.bindPort);
1974+
logInfo("Listening for requests on %s://%s/", proto,
1975+
bind_address.toString().replace("/", "%2f"));
19451976
return ret;
19461977
} catch( Exception e ) {
19471978
logWarn("Failed to listen on %s:%s", listen_info.bindAddress, listen_info.bindPort);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name "tests"
2+
description "Unix Sockets"
3+
dependency "vibe-http" path="../../"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import vibe.core.file;
2+
import vibe.inet.url;
3+
import vibe.http.client;
4+
import vibe.http.server;
5+
import vibe.http.router;
6+
import vibe.stream.operations;
7+
import std.stdio;
8+
9+
void handleHelloRequest(scope HTTPServerRequest req, scope HTTPServerResponse res)
10+
{
11+
res.writeBody("Hello, World!", "text/plain");
12+
}
13+
14+
void main()
15+
{
16+
version (Posix) {
17+
if (existsFile("/tmp/vibe.sock"))
18+
removeFile("/tmp/vibe.sock");
19+
20+
auto router = new URLRouter;
21+
router.get("/hello", &handleHelloRequest);
22+
23+
auto settings = new HTTPServerSettings;
24+
settings.bindAddresses = ["/tmp/vibe.sock"];
25+
26+
listenHTTP(settings, router);
27+
28+
requestHTTP("http+unix://%2ftmp%2fvibe.sock/hello", (scope req) {}, (scope res) {
29+
assert(res.bodyReader.readAllUTF8() == "Hello, World!");
30+
});
31+
32+
removeFile("/tmp/vibe.sock");
33+
} else logInfo("Skipping test on non-Posix platform.");
34+
}

0 commit comments

Comments
 (0)