Skip to content

Commit 84f896d

Browse files
committed
Only query the remote address for incoming HTTP connections at the beginning.
Fixes possible errors when attempting to query the address on an already closed connection and avoids some computational overhead.
1 parent e97838b commit 84f896d

File tree

4 files changed

+27
-16
lines changed

4 files changed

+27
-16
lines changed

source/vibe/http/internal/http1/server.d

+5-5
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import std.format : format, formattedWrite;
3636
context = Information about the incoming listener and available
3737
virtual hosts
3838
*/
39-
void handleHTTP1Connection(TLSStreamType)(TCPConnection connection, TLSStreamType tls_stream, StreamProxy http_stream, HTTPServerContext context)
39+
void handleHTTP1Connection(TLSStreamType)(TCPConnection connection, TLSStreamType tls_stream, StreamProxy http_stream, HTTPServerContext context, ref NetworkAddress remote_address)
4040
@safe {
4141

4242
while (!connection.empty) {
@@ -52,7 +52,7 @@ void handleHTTP1Connection(TLSStreamType)(TCPConnection connection, TLSStreamTyp
5252
scope request_allocator = createRequestAllocator();
5353
scope (exit) freeRequestAllocator(request_allocator);
5454

55-
handleRequest!TLSStreamType(http_stream, connection, context, settings, keep_alive, request_allocator);
55+
handleRequest!TLSStreamType(http_stream, connection, context, settings, keep_alive, request_allocator, remote_address);
5656
} ();
5757
if (!keep_alive) { logTrace("No keep-alive - disconnecting client."); break; }
5858

@@ -67,7 +67,7 @@ void handleHTTP1Connection(TLSStreamType)(TCPConnection connection, TLSStreamTyp
6767
}
6868

6969

70-
private bool handleRequest(TLSStreamType, Allocator)(StreamProxy http_stream, TCPConnection tcp_connection, HTTPServerContext listen_info, ref HTTPServerSettings settings, ref bool keep_alive, scope Allocator request_allocator)
70+
private bool handleRequest(TLSStreamType, Allocator)(StreamProxy http_stream, TCPConnection tcp_connection, HTTPServerContext listen_info, ref HTTPServerSettings settings, ref bool keep_alive, scope Allocator request_allocator, ref NetworkAddress remote_address)
7171
@safe {
7272
import vibe.container.internal.utilallocator : make, dispose;
7373
import vibe.http.internal.utils : formatRFC822DateAlloc;
@@ -85,7 +85,7 @@ private bool handleRequest(TLSStreamType, Allocator)(StreamProxy http_stream, TC
8585
FreeListRef!ChunkedInputStream chunked_input_stream;
8686

8787
// store the IP address
88-
req.clientAddress = tcp_connection.remoteAddress;
88+
req.clientAddress = remote_address;
8989

9090
if (!listen_info.hasVirtualHosts) {
9191
logWarn("Didn't find a HTTP listening context for incoming connection. Dropping.");
@@ -164,7 +164,7 @@ private bool handleRequest(TLSStreamType, Allocator)(StreamProxy http_stream, TC
164164

165165
http_stream.read(dummy); // finish reading connection preface
166166
auto h2settings = HTTP2Settings();
167-
auto h2context = new HTTP2ServerContext(listen_info, h2settings);
167+
auto h2context = new HTTP2ServerContext(listen_info, h2settings, remote_address);
168168
handleHTTP2Connection(tcp_connection, tcp_connection, h2context, true);
169169
return true;
170170
}

source/vibe/http/internal/http2/exchange.d

+3-2
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ unittest {
124124
import std.experimental.allocator.mallocator;
125125
HTTP2Settings settings;
126126
HTTPServerContext ctx;
127-
auto context = new HTTP2ServerContext(ctx, settings);
127+
NetworkAddress raddr;
128+
auto context = new HTTP2ServerContext(ctx, settings, raddr);
128129
auto table = IndexingTable(settings.headerTableSize);
129130
scope alloc = new RegionListAllocator!(shared(Mallocator), false)(1024, Mallocator.instance);
130131

@@ -167,7 +168,7 @@ bool handleHTTP2Request(UStream)(ref HTTP2ConnectionStream!UStream stream,
167168
auto req = () @trusted { return alloc.make!HTTPServerRequest(reqtime, listen_info.bindPort); } ();
168169
scope (exit) () @trusted { alloc.dispose(req); } ();
169170
// store the IP address
170-
req.clientAddress = tcp_connection.remoteAddress;
171+
req.clientAddress = h2context.remoteAddress;
171172

172173
if (!listen_info.hasVirtualHosts) {
173174
logWarn("Didn't find a HTTP listening context for incoming connection. Dropping.");

source/vibe/http/internal/http2/settings.d

+6-3
Original file line numberDiff line numberDiff line change
@@ -313,25 +313,28 @@ final class HTTP2ServerContext
313313
FreeListRef!HTTP2Multiplexer m_multiplexer;
314314
bool m_initializedT = false;
315315
bool m_initializedM = false;
316-
316+
NetworkAddress m_remoteAddress;
317317
}
318318

319319
alias m_context this;
320320

321321
// used to mantain the first request in case of `h2c` protocol switching
322322
ubyte[] resFrame = void;
323323

324-
this(HTTPServerContext ctx, HTTP2Settings settings) @safe
325-
{
324+
this(HTTPServerContext ctx, HTTP2Settings settings, ref NetworkAddress remote_address)
325+
@safe {
326326
m_context = ctx;
327327
m_settings = settings;
328+
m_remoteAddress = remote_address;
328329
}
329330

330331
this(HTTPServerContext ctx) @safe
331332
{
332333
m_context = ctx;
333334
}
334335

336+
@property ref const(NetworkAddress) remoteAddress() const @safe { return m_remoteAddress; }
337+
335338
@property auto ref table() @safe { return m_table.get; }
336339

337340
@property bool hasTable() @safe { return m_initializedT; }

source/vibe/http/server.d

+13-6
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ unittest
193193
virtual hosts
194194
*/
195195
void handleHTTPConnection(TCPConnection connection, HTTPServerContext context)
196+
@safe {
197+
auto raddr = connection.remoteAddress;
198+
handleHTTPConnection(connection, context, raddr);
199+
}
200+
/// ditto
201+
void handleHTTPConnection(TCPConnection connection, HTTPServerContext context, ref NetworkAddress remote_address)
196202
@safe {
197203
import vibe.http.internal.http1.server : handleHTTP1Connection;
198204
import vibe.http.internal.http2.server : handleHTTP2Connection;
@@ -212,7 +218,7 @@ void handleHTTPConnection(TCPConnection connection, HTTPServerContext context)
212218
// check wether the client's address is banned
213219
foreach (ref virtual_host; context.m_virtualHosts)
214220
if ((virtual_host.settings.rejectConnectionPredicate !is null) &&
215-
virtual_host.settings.rejectConnectionPredicate(connection.remoteAddress()))
221+
virtual_host.settings.rejectConnectionPredicate(remote_address))
216222
return;
217223

218224
// Set NODELAY to true, to avoid delays caused by sending the response
@@ -235,13 +241,13 @@ void handleHTTPConnection(TCPConnection connection, HTTPServerContext context)
235241
else {
236242
logDebug("Accept TLS connection: %s", context.tlsContext.kind);
237243
// TODO: reverse DNS lookup for peer_name of the incoming connection for TLS client certificate verification purposes
238-
tls_stream = createTLSStreamFL(http_stream, context.tlsContext, TLSStreamState.accepting, null, connection.remoteAddress);
244+
tls_stream = createTLSStreamFL(http_stream, context.tlsContext, TLSStreamState.accepting, null, remote_address);
239245

240246
Nullable!string proto = tls_stream.alpn;
241247
if(!proto.isNull && proto == "h2" && (context.m_virtualHosts[0].settings.options & HTTPServerOption.enableHTTP2)) {
242248
logTrace("Using HTTP/2 as requested per ALPN");
243249
HTTP2Settings settings;
244-
auto h2context = new HTTP2ServerContext(context, settings);
250+
auto h2context = new HTTP2ServerContext(context, settings, remote_address);
245251
handleHTTP2Connection(tls_stream, connection, h2context);
246252
return;
247253
}
@@ -250,7 +256,7 @@ void handleHTTPConnection(TCPConnection connection, HTTPServerContext context)
250256
}
251257
}
252258

253-
handleHTTP1Connection(connection, tls_stream, http_stream, context);
259+
handleHTTP1Connection(connection, tls_stream, http_stream, context, remote_address);
254260

255261
logTrace("Done handling connection.");
256262
}
@@ -1900,9 +1906,10 @@ private HTTPListener listenHTTPPlain(HTTPServerSettings settings, HTTPServerRequ
19001906
if(reuseAddress) options |= TCPListenOptions.reuseAddress; else options &= ~TCPListenOptions.reuseAddress;
19011907
if(reusePort) options |= TCPListenOptions.reusePort; else options &= ~TCPListenOptions.reusePort;
19021908
auto ret = listenTCP(listen_info.bindPort, (TCPConnection conn) nothrow @safe {
1903-
try handleHTTPConnection(conn, listen_info);
1909+
auto raddr = conn.remoteAddress;
1910+
try handleHTTPConnection(conn, listen_info, raddr);
19041911
catch (Exception e) {
1905-
logError("HTTP connection handler has thrown at the peer %s: %s", conn.peerAddress, e.msg);
1912+
logError("HTTP connection handler has thrown at the peer %s: %s", raddr, e.msg);
19061913
debug logDebug("Full error: %s", () @trusted { return e.toString().sanitize(); } ());
19071914
try conn.close();
19081915
catch (Exception e) logError("Failed to close connection: %s", e.msg);

0 commit comments

Comments
 (0)