diff options
-rw-r--r-- | src/net/tcp/httpconn.c | 9 | ||||
-rw-r--r-- | src/net/tcp/httpcore.c | 12 |
2 files changed, 19 insertions, 2 deletions
diff --git a/src/net/tcp/httpconn.c b/src/net/tcp/httpconn.c index 2cfca9c9..5121ff6c 100644 --- a/src/net/tcp/httpconn.c +++ b/src/net/tcp/httpconn.c @@ -252,8 +252,13 @@ int http_connect ( struct interface *xfer, struct uri *uri ) { /* Identify port */ port = uri_port ( uri, scheme->port ); - /* Look for a reusable connection in the pool */ - list_for_each_entry ( conn, &http_connection_pool, pool.list ) { + /* Look for a reusable connection in the pool. Reuse the most + * recent connection in order to accommodate authentication + * schemes that break the stateless nature of HTTP and rely on + * the same connection being reused for authentication + * responses. + */ + list_for_each_entry_reverse ( conn, &http_connection_pool, pool.list ) { /* Sanity checks */ assert ( conn->uri != NULL ); diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index b3c9a00e..f755fb72 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -778,6 +778,18 @@ static int http_transfer_complete ( struct http_transaction *http ) { http->len = 0; assert ( http->remaining == 0 ); + /* Retry immediately if applicable. We cannot rely on an + * immediate timer expiry, since certain Microsoft-designed + * HTTP extensions such as NTLM break the fundamentally + * stateless nature of HTTP and rely on the same connection + * being reused for authentication. See RFC7230 section 2.3 + * for further details. + */ + if ( ! http->response.retry_after ) { + http_reopen ( http ); + return 0; + } + /* Start timer to initiate retry */ DBGC2 ( http, "HTTP %p retrying after %d seconds\n", http, http->response.retry_after ); |