diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index de5eae42ce..dc13fd093c 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -1807,20 +1807,23 @@ static DWORD set_content_length( request_t *request, DWORD status ) WCHAR encoding[20]; DWORD buflen = sizeof(request->content_length); - if (status == HTTP_STATUS_NO_CONTENT || status == HTTP_STATUS_NOT_MODIFIED) + if (status == HTTP_STATUS_NO_CONTENT || status == HTTP_STATUS_NOT_MODIFIED || !strcmpW( request->verb, headW )) 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); - if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) && - !strcmpiW( encoding, chunkedW )) + else { - request->content_length = ~0u; - request->read_chunked = TRUE; - request->read_chunked_size = ~0u; - request->read_chunked_eof = FALSE; + 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); + if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) && + !strcmpiW( encoding, chunkedW )) + { + request->content_length = ~0u; + request->read_chunked = TRUE; + request->read_chunked_size = ~0u; + request->read_chunked_eof = FALSE; + } } request->content_read = 0; return request->content_length; @@ -1969,6 +1972,7 @@ static DWORD get_available_data( request_t *request ) /* check if we have reached the end of the data to read */ static BOOL end_of_read_data( request_t *request ) { + if (!request->content_length) return TRUE; if (request->read_chunked) return request->read_chunked_eof; if (request->content_length == ~0u) return FALSE; return (request->content_length == request->content_read); @@ -2394,8 +2398,11 @@ BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved ) static BOOL query_data_available( request_t *request, DWORD *available, BOOL async ) { - DWORD count = get_available_data( request ); + DWORD count = 0; + if (end_of_read_data( request )) goto done; + + count = get_available_data( request ); if (!request->read_chunked) count += netconn_query_data_available( &request->netconn ); if (!count) @@ -2406,6 +2413,7 @@ static BOOL query_data_available( request_t *request, DWORD *available, BOOL asy count += netconn_query_data_available( &request->netconn ); } +done: if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &count, sizeof(count) ); TRACE("%u bytes available\n", count); if (available) *available = count; diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index 384df23dd5..2cad807c6d 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -1818,6 +1818,11 @@ static const char okauthmsg[] = "Connection: close\r\n" "\r\n"; +static const char headmsg[] = +"HTTP/1.1 200 OK\r\n" +"Content-Length: 100\r\n" +"\r\n"; + struct server_info { HANDLE event; @@ -1904,6 +1909,11 @@ static DWORD CALLBACK server_thread(LPVOID param) send(c, notmodified, sizeof notmodified - 1, 0); continue; } + if (strstr(buffer, "HEAD /head")) + { + send(c, headmsg, sizeof headmsg - 1, 0); + continue; + } if (strstr(buffer, "GET /quit")) { send(c, okmsg, sizeof okmsg - 1, 0); @@ -2220,6 +2230,65 @@ static void test_no_content(int port) WinHttpCloseHandle(ses); } +static void test_head_request(int port) +{ + static const WCHAR verbW[] = {'H','E','A','D',0}; + static const WCHAR headW[] = {'/','h','e','a','d',0}; + HINTERNET ses, con, req; + char buf[128]; + DWORD size, len, count, status; + BOOL ret; + + ses = WinHttpOpen(test_useragent, 0, NULL, NULL, 0); + ok(ses != NULL, "failed to open session %u\n", GetLastError()); + + con = WinHttpConnect(ses, localhostW, port, 0); + ok(con != NULL, "failed to open a connection %u\n", GetLastError()); + + req = WinHttpOpenRequest(con, verbW, headW, NULL, NULL, NULL, 0); + ok(req != NULL, "failed to open a request %u\n", GetLastError()); + + ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0); + ok(ret, "failed to send request %u\n", GetLastError()); + + ret = WinHttpReceiveResponse(req, NULL); + ok(ret, "failed to receive response %u\n", GetLastError()); + + status = 0xdeadbeef; + size = sizeof(status); + ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, + NULL, &status, &size, NULL); + ok(ret, "failed to get status code %u\n", GetLastError()); + ok(status == 200, "got %u\n", status); + + len = 0xdeadbeef; + size = sizeof(len); + ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, + NULL, &len, &size, 0); + ok(ret, "failed to get content-length header %u\n", GetLastError()); + ok(len == 100, "got %u\n", len); + + count = 0xdeadbeef; + ret = WinHttpQueryDataAvailable(req, &count); + ok(ret, "failed to query data available %u\n", GetLastError()); + ok(!count, "got %u\n", count); + + len = sizeof(buf); + count = 0xdeadbeef; + ret = WinHttpReadData(req, buf, len, &count); + ok(ret, "failed to read data %u\n", GetLastError()); + ok(!count, "got %u\n", count); + + count = 0xdeadbeef; + ret = WinHttpQueryDataAvailable(req, &count); + ok(ret, "failed to query data available %u\n", GetLastError()); + ok(!count, "got %u\n", count); + + WinHttpCloseHandle(req); + WinHttpCloseHandle(con); + 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}; @@ -3278,6 +3347,7 @@ START_TEST (winhttp) test_basic_request(si.port, NULL, basicW); test_no_headers(si.port); test_no_content(si.port); + test_head_request(si.port); test_not_modified(si.port); test_basic_authentication(si.port); test_bad_header(si.port);