diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 62ecfee6615..61f5439efd1 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -1802,14 +1802,15 @@ static BOOL handle_authorization( request_t *request, DWORD status ) } /* set the request content length based on the headers */ -static DWORD set_content_length( request_t *request ) +static DWORD set_content_length( request_t *request, DWORD status ) { WCHAR encoding[20]; - DWORD buflen; + DWORD buflen = sizeof(request->content_length); - buflen = sizeof(request->content_length); - if (!query_headers( request, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER, - NULL, &request->content_length, &buflen, NULL )) + if (status == HTTP_STATUS_NO_CONTENT || status == HTTP_STATUS_NOT_MODIFIED) + request->content_length = 0; + else if (!query_headers( request, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER, + NULL, &request->content_length, &buflen, NULL )) request->content_length = ~0u; buflen = sizeof(encoding); @@ -2302,7 +2303,7 @@ static BOOL receive_response( request_t *request, BOOL async ) query = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER; if (!(ret = query_headers( request, query, NULL, &status, &size, NULL ))) break; - set_content_length( request ); + set_content_length( request, status ); if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request ); @@ -2329,7 +2330,7 @@ static BOOL receive_response( request_t *request, BOOL async ) break; } - if (ret) refill_buffer( request, FALSE ); + if (request->content_length) refill_buffer( request, FALSE ); if (async) { diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index 8a863cbf44b..7d0167b8620 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -1801,6 +1801,10 @@ static const char nocontentmsg[] = "Server: winetest\r\n" "\r\n"; +static const char notmodified[] = +"HTTP/1.1 304 Not Modified\r\n" +"\r\n"; + static const char noauthmsg[] = "HTTP/1.1 401 Unauthorized\r\n" "Server: winetest\r\n" @@ -1888,6 +1892,11 @@ static DWORD CALLBACK server_thread(LPVOID param) { send(c, nocontentmsg, sizeof nocontentmsg - 1, 0); } + if (strstr(buffer, "GET /not_modified")) + { + send(c, notmodified, sizeof notmodified - 1, 0); + Sleep(6000); + } if (strstr(buffer, "GET /quit")) { send(c, okmsg, sizeof okmsg - 1, 0); @@ -2129,7 +2138,7 @@ static void test_no_content(int port) { static const WCHAR no_contentW[] = {'/','n','o','_','c','o','n','t','e','n','t',0}; HINTERNET ses, con, req; - WCHAR buf[128]; + char buf[128]; DWORD size, len = sizeof(buf), bytes_read, status; BOOL ret; @@ -2181,6 +2190,7 @@ static void test_no_content(int port) ok(size == 0, "expected 0, got %d\n", size); ret = WinHttpReadData(req, buf, len, &bytes_read); + ok(ret, "expected success\n"); ok( bytes_read == 0, "expected 0, got %u available\n", bytes_read ); size = 12345; @@ -2202,6 +2212,55 @@ static void test_no_content(int port) WinHttpCloseHandle(ses); } +static void test_not_modified(int port) +{ + static const WCHAR pathW[] = {'/','n','o','t','_','m','o','d','i','f','i','e','d',0}; + static const WCHAR ifmodifiedW[] = {'I','f','-','M','o','d','i','f','i','e','d','-','S','i','n','c','e',':',' '}; + BOOL ret; + HINTERNET session, request, connection; + DWORD status, size, start = GetTickCount(); + SYSTEMTIME st; + WCHAR today[(sizeof(ifmodifiedW) + WINHTTP_TIME_FORMAT_BUFSIZE)/sizeof(WCHAR) + 3]; + + memcpy(today, ifmodifiedW, sizeof(ifmodifiedW)); + GetSystemTime(&st); + WinHttpTimeFromSystemTime(&st, &today[sizeof(ifmodifiedW)/sizeof(WCHAR)]); + + session = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, + WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + ok(session != NULL, "WinHttpOpen failed: %u\n", GetLastError()); + + connection = WinHttpConnect(session, localhostW, port, 0); + ok(connection != NULL, "WinHttpConnect failed: %u\n", GetLastError()); + + request = WinHttpOpenRequest(connection, NULL, pathW, NULL, WINHTTP_NO_REFERER, + WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_BYPASS_PROXY_CACHE); + ok(request != NULL, "WinHttpOpenrequest failed: %u\n", GetLastError()); + + ret = WinHttpSendRequest(request, today, ~0u, NULL, 0, 0, 0); + ok(ret, "WinHttpSendRequest failed: %u\n", GetLastError()); + + ret = WinHttpReceiveResponse(request, NULL); + ok(ret, "WinHttpReceiveResponse failed: %u\n", GetLastError()); + + size = sizeof(status); + ret = WinHttpQueryHeaders(request, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, + NULL, &status, &size, NULL); + ok(ret, "WinHttpQueryHeaders failed: %u\n", GetLastError()); + ok(status == HTTP_STATUS_NOT_MODIFIED, "got %u\n", status); + + size = 0xdeadbeef; + ret = WinHttpQueryDataAvailable(request, &size); + ok(ret, "WinHttpQueryDataAvailable failed: %u\n", GetLastError()); + ok(!size, "got %u\n", size); + + WinHttpCloseHandle(request); + WinHttpCloseHandle(connection); + WinHttpCloseHandle(session); + start = GetTickCount() - start; + ok(start <= 2000, "Expected less than 2 seconds for the test, got %u ms\n", start); +} + static void test_bad_header( int port ) { static const WCHAR bad_headerW[] = @@ -3211,6 +3270,7 @@ START_TEST (winhttp) test_basic_request(si.port, NULL, basicW); test_no_headers(si.port); test_no_content(si.port); + test_not_modified(si.port); test_basic_authentication(si.port); test_bad_header(si.port); test_multiple_reads(si.port);