This documentation is also published as Markdown for efficient machine reading: the whole site is indexed at /llms.txt, and every page has a clean Markdown copy at the same URL with .md appended. These are generated from the same source and cost far fewer tokens to read than this rendered HTML.

Skip to main content Skip to navigation

HttpDispatcher Pennington.Infrastructure

Default IInProcessHttpDispatcher. Inspects the registered IServer and returns an in-memory client when it's a TestServer, or a socket-bound client pointing at Kestrel's listening address otherwise.

The handler chain is built once and shared by every client this dispatcher hands out — clients are cheap wrappers created with disposeHandler: false, so a caller's using releases the wrapper without tearing down the connection pool. This matters on the Kestrel path: SiteProjection issues one fetch per page, and a per-fetch handler cannot pool, so every fetch opened a fresh loopback socket that then sat in TIME_WAIT. A corpus larger than the ~16k Windows ephemeral port range exhausted it partway through and the remaining fetches failed with SocketError.AddressAlreadyInUse — silently dropping those pages from the search index and llms.txt, since RenderOneAsync treats a failed fetch as a per-page error.

Constructors

HttpDispatcher

#
public HttpDispatcher(IServer server, BuildHtmlCache cache)

Initializes the dispatcher with the host's registered IServer and the shared render cache.

Parameters

server IServer
cache BuildHtmlCache

Methods

CreateClient

#
public HttpClient CreateClient()

Returns an HttpClient whose requests flow through the running app's pipeline.

Returns

HttpClient

Dispose

#
public void Dispose()

Disposes the shared handler chain and its pooled connections.

Pennington.Infrastructure.HttpDispatcher

namespace Pennington.Infrastructure;

/// Default IInProcessHttpDispatcher. Inspects the registered IServer and returns an in-memory client when it's a TestServer, or a socket-bound client pointing at Kestrel's listening address otherwise. The handler chain is built once and shared by every client this dispatcher hands out — clients are cheap wrappers created with disposeHandler: false, so a caller's using releases the wrapper without tearing down the connection pool. This matters on the Kestrel path: SiteProjection issues one fetch per page, and a per-fetch handler cannot pool, so every fetch opened a fresh loopback socket that then sat in TIME_WAIT. A corpus larger than the ~16k Windows ephemeral port range exhausted it partway through and the remaining fetches failed with SocketError.AddressAlreadyInUse — silently dropping those pages from the search index and llms.txt, since RenderOneAsync treats a failed fetch as a per-page error.
public class HttpDispatcher
{
    /// Returns an HttpClient whose requests flow through the running app's pipeline.
    
public HttpClient CreateClient()
; /// Disposes the shared handler chain and its pooled connections.
public void Dispose()
; /// Initializes the dispatcher with the host's registered IServer and the shared render cache.
public HttpDispatcher(IServer server, BuildHtmlCache cache)
; }