|
| 1 | +From 4482b184e4321533205750f9a8f64e7c4018b259 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Johannes Schindelin < [email protected]> |
| 3 | +Date: Fri, 7 Dec 2018 17:04:39 +0100 |
| 4 | +Subject: [PATCH 4/4] Upon HTTP_1_1_REQUIRED, retry the request with HTTP/1.1 |
| 5 | + |
| 6 | +This is a companion patch to cbea2fd2c (NTLM: force the connection to |
| 7 | +HTTP/1.1, 2018-12-06): with NTLM, we can switch to HTTP/1.1 |
| 8 | +preemptively. However, with other (Negotiate) authentication it is not |
| 9 | +clear to this developer whether there is a way to make it work with |
| 10 | +HTTP/2, so let's try HTTP/2 first and fall back in case we encounter the |
| 11 | +error HTTP_1_1_REQUIRED. |
| 12 | + |
| 13 | +Note: we will still keep the NTLM workaround, as it avoids an extra |
| 14 | +round trip. |
| 15 | + |
| 16 | +Daniel Stenberg helped a lot with this patch, in particular by |
| 17 | +suggesting to introduce the Curl_h2_http_1_1_error() function. |
| 18 | + |
| 19 | +Closes #3349 |
| 20 | + |
| 21 | +Signed-off-by: Johannes Schindelin < [email protected]> |
| 22 | +--- |
| 23 | + lib/http2.c | 8 ++++++++ |
| 24 | + lib/http2.h | 4 ++++ |
| 25 | + lib/multi.c | 20 ++++++++++++++++++++ |
| 26 | + 3 files changed, 32 insertions(+) |
| 27 | + |
| 28 | +diff --git a/lib/http2.c b/lib/http2.c |
| 29 | +index 0c5f6db0b..424724ab7 100644 |
| 30 | +--- a/lib/http2.c |
| 31 | ++++ b/lib/http2.c |
| 32 | +@@ -2367,6 +2367,14 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data) |
| 33 | + Curl_http2_remove_child(data->set.stream_depends_on, data); |
| 34 | + } |
| 35 | + |
| 36 | ++/* Only call this function for a transfer that already got a HTTP/2 |
| 37 | ++ CURLE_HTTP2_STREAM error! */ |
| 38 | ++bool Curl_h2_http_1_1_error(struct connectdata *conn) |
| 39 | ++{ |
| 40 | ++ struct http_conn *httpc = &conn->proto.httpc; |
| 41 | ++ return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED); |
| 42 | ++} |
| 43 | ++ |
| 44 | + #else /* !USE_NGHTTP2 */ |
| 45 | + |
| 46 | + /* Satisfy external references even if http2 is not compiled in. */ |
| 47 | +diff --git a/lib/http2.h b/lib/http2.h |
| 48 | +index 4492ec211..67db3dffb 100644 |
| 49 | +--- a/lib/http2.h |
| 50 | ++++ b/lib/http2.h |
| 51 | +@@ -59,6 +59,9 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent, |
| 52 | + void Curl_http2_remove_child(struct Curl_easy *parent, |
| 53 | + struct Curl_easy *child); |
| 54 | + void Curl_http2_cleanup_dependencies(struct Curl_easy *data); |
| 55 | ++ |
| 56 | ++/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */ |
| 57 | ++bool Curl_h2_http_1_1_error(struct connectdata *conn); |
| 58 | + #else /* USE_NGHTTP2 */ |
| 59 | + #define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL |
| 60 | + #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL |
| 61 | +@@ -74,6 +77,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data); |
| 62 | + #define Curl_http2_add_child(x, y, z) |
| 63 | + #define Curl_http2_remove_child(x, y) |
| 64 | + #define Curl_http2_cleanup_dependencies(x) |
| 65 | ++#define Curl_h2_http_1_1_error(x) 0 |
| 66 | + #endif |
| 67 | + |
| 68 | + #endif /* HEADER_CURL_HTTP2_H */ |
| 69 | +diff --git a/lib/multi.c b/lib/multi.c |
| 70 | +index 0db2a9730..ebd9189d2 100644 |
| 71 | +--- a/lib/multi.c |
| 72 | ++++ b/lib/multi.c |
| 73 | +@@ -46,6 +46,7 @@ |
| 74 | + #include "vtls/vtls.h" |
| 75 | + #include "connect.h" |
| 76 | + #include "http_proxy.h" |
| 77 | ++#include "http2.h" |
| 78 | + /* The last 3 #include files should be in this order */ |
| 79 | + #include "curl_printf.h" |
| 80 | + #include "curl_memory.h" |
| 81 | +@@ -1939,6 +1940,25 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi, |
| 82 | + done = TRUE; |
| 83 | + } |
| 84 | + } |
| 85 | ++ else if((CURLE_HTTP2_STREAM == result) && |
| 86 | ++ Curl_h2_http_1_1_error(data->easy_conn)) { |
| 87 | ++ CURLcode ret = Curl_retry_request(data->easy_conn, &newurl); |
| 88 | ++ |
| 89 | ++ infof(data, "Forcing HTTP/1.1 for NTLM"); |
| 90 | ++ data->set.httpversion = CURL_HTTP_VERSION_1_1; |
| 91 | ++ |
| 92 | ++ if(!ret) |
| 93 | ++ retry = (newurl)?TRUE:FALSE; |
| 94 | ++ else |
| 95 | ++ result = ret; |
| 96 | ++ |
| 97 | ++ if(retry) { |
| 98 | ++ /* if we are to retry, set the result to OK and consider the |
| 99 | ++ request as done */ |
| 100 | ++ result = CURLE_OK; |
| 101 | ++ done = TRUE; |
| 102 | ++ } |
| 103 | ++ } |
| 104 | + |
| 105 | + if(result) { |
| 106 | + /* |
| 107 | +-- |
| 108 | +2.19.2.windows.1.19.g96889860afc7 |
| 109 | + |
0 commit comments