Module: wine Branch: master Commit: 0080205dbd15e873204496df6411b1eee50ff482 URL: https://gitlab.winehq.org/wine/wine/-/commit/0080205dbd15e873204496df6411b1e...
Author: Paul Gofman pgofman@codeweavers.com Date: Fri Dec 1 21:30:30 2023 -0600
winhttp: Handle chunked requests.
---
dlls/winhttp/request.c | 10 ++++++-- dlls/winhttp/tests/winhttp.c | 55 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 61 insertions(+), 4 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index aed26d98c07..84af8e58988 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -2216,8 +2216,10 @@ static DWORD send_request( struct request *request, const WCHAR *headers, DWORD struct connect *connect = request->connect; struct session *session = connect->session; DWORD ret, len, buflen, content_length; + WCHAR encoding[20]; char *wire_req; int bytes_sent; + BOOL chunked;
TRACE( "request state %d.\n", request->state );
@@ -2245,7 +2247,11 @@ static DWORD send_request( struct request *request, const WCHAR *headers, DWORD if (request->creds[TARGET_SERVER][SCHEME_BASIC].username) do_authorization( request, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC );
- if (total_len || (request->verb && (!wcscmp( request->verb, L"POST" ) || !wcscmp( request->verb, L"PUT" )))) + buflen = sizeof(encoding); + chunked = !query_headers( request, WINHTTP_QUERY_FLAG_REQUEST_HEADERS | WINHTTP_QUERY_TRANSFER_ENCODING, + NULL, encoding, &buflen, NULL ) && !wcsicmp( encoding, L"chunked" ); + if (!chunked && (total_len || (request->verb && (!wcscmp( request->verb, L"POST" ) + || !wcscmp( request->verb, L"PUT" ))))) { WCHAR length[21]; /* decimal long int + null */ swprintf( length, ARRAY_SIZE(length), L"%ld", total_len ); @@ -2311,7 +2317,7 @@ static DWORD send_request( struct request *request, const WCHAR *headers, DWORD | WINHTTP_QUERY_FLAG_NUMBER, NULL, &content_length, &buflen, NULL )) content_length = total_len;
- if (content_length <= optional_len) + if (!chunked && content_length <= optional_len) { netconn_set_timeout( request->netconn, FALSE, request->receive_response_timeout ); request->read_reply_status = read_reply( request ); diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index ce2ce795209..09abc4c5854 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -2541,9 +2541,21 @@ static DWORD CALLBACK server_thread(LPVOID param) ok(!!strstr(buffer, "Cookie: 111\r\n"), "Header missing from request %s.\n", debugstr_a(buffer)); send(c, okmsg, sizeof(okmsg) - 1, 0); } - if (strstr(buffer, "PUT /test")) + + if (strstr(buffer, "PUT /test") || strstr(buffer, "POST /test")) { - ok(!!strstr(buffer, "Content-Length: 0\r\n"), "Header missing from request %s.\n", debugstr_a(buffer)); + if (strstr(buffer, "Transfer-Encoding: chunked\r\n")) + { + ok(!strstr(buffer, "Content-Length:"), "Unexpected Content-Length in request %s.\n", debugstr_a(buffer)); + r = recv(c, buffer, sizeof(buffer), 0); + ok(r == 4, "got %d.\n", r); + buffer[r] = 0; + ok(!strcmp(buffer, "post"), "got %s.\n", debugstr_a(buffer)); + } + else + { + ok(!!strstr(buffer, "Content-Length: 0\r\n"), "Header missing from request %s.\n", debugstr_a(buffer)); + } send(c, okmsg, sizeof(okmsg) - 1, 0); } shutdown(c, 2); @@ -2653,6 +2665,44 @@ static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path) WinHttpCloseHandle(ses); }
+static void test_chunked_request(int port) +{ + static const WCHAR *methods[] = {L"POST", L"PUT"}; + HINTERNET ses, con, req; + char buffer[0x100]; + unsigned int i; + DWORD count; + BOOL ret; + + ses = WinHttpOpen(L"winetest", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0); + ok(ses != NULL, "failed to open session %lu\n", GetLastError()); + + con = WinHttpConnect(ses, L"localhost", port, 0); + ok(con != NULL, "failed to open a connection %lu\n", GetLastError()); + for (i = 0; i < ARRAY_SIZE(methods); ++i) + { + req = WinHttpOpenRequest(con, methods[i], L"/test", NULL, NULL, NULL, 0); + ok(req != NULL, "failed to open a request %lu\n", GetLastError()); + + ret = WinHttpAddRequestHeaders(req, L"Transfer-Encoding: chunked", -1, WINHTTP_ADDREQ_FLAG_ADD); + ok(ret, "failed to add header %lu\n", GetLastError()); + + strcpy(buffer, "post"); + ret = WinHttpSendRequest(req, NULL, 0, buffer, 4, 4, 0); + ok(ret, "failed to send request %lu\n", GetLastError()); + ret = WinHttpReceiveResponse(req, NULL); + ok(ret, "failed to receive response %lu\n", GetLastError()); + count = 0; + memset(buffer, 0, sizeof(buffer)); + ret = WinHttpReadData(req, buffer, sizeof buffer, &count); + ok(ret, "failed to read data %lu\n", GetLastError()); + ok(!count, "got count %ld\n", count); + WinHttpCloseHandle(req); + } + WinHttpCloseHandle(con); + WinHttpCloseHandle(ses); +} + static void test_basic_authentication(int port) { HINTERNET ses, con, req; @@ -5824,6 +5874,7 @@ START_TEST (winhttp) test_connection_info(si.port); test_basic_request(si.port, NULL, L"/basic"); test_basic_request(si.port, L"PUT", L"/test"); + test_chunked_request(si.port); test_no_headers(si.port); test_no_content(si.port); test_head_request(si.port);