hrev47586 adds 4 changesets to branch 'master' old head: ae2cdda73621bfd3fc5a73f60a49514d00bbffa4 new head: a1cce97050323eca3dc37d2d44eaf89b3e0be323 overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=a1cce97+%5Eae2cdda ---------------------------------------------------------------------------- 021ebc2: Add the port to the HTTP Host header when needed. * When the port is not the default one, it must be added to the "Host" header so the server knows what we're connecting to. Fixes #11070. 548149f: Fix out-of-date comment. 4359643: Test for relative URL with a port in the base URL. As expected, the port is preserved. a1cce97: HttpRequest: more small fixes and cleanups * Remove unneeded field fOutputHeaders and convert it to a local for the only method that uses it, * Don't return EOVERFLOW when flushing data from ZLib (the ZLib decompressor returns this, but zlib docs states that this is NOT an error condition). * Replace unneeded temporary BNetBuffer of fixed size with BStackOrHeapArray. [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- 4 files changed, 61 insertions(+), 32 deletions(-) headers/os/net/HttpRequest.h | 4 +- headers/tools/cppunit/TestShell.h | 10 ++-- src/kits/network/libnetapi/HttpRequest.cpp | 69 +++++++++++++++++--------- src/tests/kits/net/service/UrlTest.cpp | 10 +++- ############################################################################ Commit: 021ebc2f8c1c004defbb817a7cdebf80b6eaf346 URL: http://cgit.haiku-os.org/haiku/commit/?id=021ebc2 Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Mon Jul 28 09:05:58 2014 UTC Ticket: https://dev.haiku-os.org/ticket/11070 Add the port to the HTTP Host header when needed. * When the port is not the default one, it must be added to the "Host" header so the server knows what we're connecting to. Fixes #11070. ---------------------------------------------------------------------------- diff --git a/headers/os/net/HttpRequest.h b/headers/os/net/HttpRequest.h index ccd0f52..f613a15 100644 --- a/headers/os/net/HttpRequest.h +++ b/headers/os/net/HttpRequest.h @@ -81,6 +81,9 @@ private: void _SetResultStatusCode(int32 statusCode); BString& _ResultStatusText(); + // Utility methods + bool _IsDefaultPort(); + private: BAbstractSocket* fSocket; BNetworkAddress fRemoteAddr; diff --git a/src/kits/network/libnetapi/HttpRequest.cpp b/src/kits/network/libnetapi/HttpRequest.cpp index 8aec11c..5fb393b 100644 --- a/src/kits/network/libnetapi/HttpRequest.cpp +++ b/src/kits/network/libnetapi/HttpRequest.cpp @@ -815,7 +815,11 @@ BHttpRequest::_SendHeaders() { // HTTP 1.1 additional headers if (fHttpVersion == B_HTTP_11) { - fOutputHeaders.AddHeader("Host", Url().Host()); + BString host = Url().Host(); + if (Url().HasPort() && !_IsDefaultPort()) + host << ':' << Url().Port(); + + fOutputHeaders.AddHeader("Host", host); fOutputHeaders.AddHeader("Accept", "*/*"); fOutputHeaders.AddHeader("Accept-Encoding", "gzip,deflate"); @@ -1041,3 +1045,15 @@ BHttpRequest::_ResultStatusText() { return fResult.fStatusString; } + + +bool BHttpRequest::_IsDefaultPort() +{ + if (fSSL && Url().Port() == 443) + return true; + if (!fSSL && Url().Port() == 80) + return true; + return false; +} + + ############################################################################ Commit: 548149fe48f59cf27f6071e9629b8bbe2ad32c1f URL: http://cgit.haiku-os.org/haiku/commit/?id=548149f Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Mon Jul 28 09:14:37 2014 UTC Fix out-of-date comment. ---------------------------------------------------------------------------- diff --git a/headers/tools/cppunit/TestShell.h b/headers/tools/cppunit/TestShell.h index f1bc371..b98993d 100644 --- a/headers/tools/cppunit/TestShell.h +++ b/headers/tools/cppunit/TestShell.h @@ -58,12 +58,10 @@ public: status_t AddSuite(BTestSuite *kit); // This function is used to add test suites to the list of available - // tests. A SuiteFunction is just a function that takes no parameters - // and returns a pointer to a CppUnit::Test object. Return NULL at - // your own risk :-). The name given is the name that will be presented - // when the program is run with "--list" as an argument. Usually the - // given suite would be a test suite for an entire class, but that's - // not a requirement. + // tests. The test pointer may not be NULL. The name given is the name that + // will be presented when the program is run with "--list" as an argument. + // Usually the given suite would be a test suite for an entire class, but + // that's not a requirement. void AddTest(const std::string &name, CppUnit::Test* test); // This function loads all the test addons it finds in the given ############################################################################ Commit: 4359643ed4016b83d1749d7425e36dd0b6a4b202 URL: http://cgit.haiku-os.org/haiku/commit/?id=4359643 Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Mon Jul 28 09:15:06 2014 UTC Test for relative URL with a port in the base URL. As expected, the port is preserved. ---------------------------------------------------------------------------- diff --git a/src/tests/kits/net/service/UrlTest.cpp b/src/tests/kits/net/service/UrlTest.cpp index 1beba92..c5c21e2 100644 --- a/src/tests/kits/net/service/UrlTest.cpp +++ b/src/tests/kits/net/service/UrlTest.cpp @@ -252,9 +252,15 @@ UrlTest::RelativeUriTest() }; const RelativeUrl tests[] = { + // The port must be preserved + {"http://host:81/";, "/path", "http://host:81/path"}, + + // Tests from http://skew.org/uri/uri_tests.html {"http://example.com/path?query#frag";, "", "http://example.com/path?query"}, - {"foo:a/b", "../c", "foo:/c"}, + // The fragment must be dropped when changing the path, but the + // query must be preserved + {"foo:a/b", "../c", "foo:/c"}, // foo:c would be more intuitive, and is what skew.org tests. // However, foo:/c is what the RFC says we should get. {"foo:a", "foo:.", "foo:"}, @@ -533,7 +539,7 @@ void UrlTest::IDNTest() { // http://www.w3.org/2004/04/uri-rel-test.html - // TODO these need to be manually UrlDecoded with ou API. + // TODO these need to be manually UrlDecoded with our API. // We also need to decide wether to store them as UTF-8 or IDNA/punycode. NextSubTest(); CPPUNIT_ASSERT_EQUAL(BUrl("http://www.w3.org";).UrlString(), ############################################################################ Revision: hrev47586 Commit: a1cce97050323eca3dc37d2d44eaf89b3e0be323 URL: http://cgit.haiku-os.org/haiku/commit/?id=a1cce97 Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Mon Jul 28 12:55:34 2014 UTC HttpRequest: more small fixes and cleanups * Remove unneeded field fOutputHeaders and convert it to a local for the only method that uses it, * Don't return EOVERFLOW when flushing data from ZLib (the ZLib decompressor returns this, but zlib docs states that this is NOT an error condition). * Replace unneeded temporary BNetBuffer of fixed size with BStackOrHeapArray. ---------------------------------------------------------------------------- diff --git a/headers/os/net/HttpRequest.h b/headers/os/net/HttpRequest.h index f613a15..080805d 100644 --- a/headers/os/net/HttpRequest.h +++ b/headers/os/net/HttpRequest.h @@ -98,7 +98,6 @@ private: // Request status - BHttpHeaders fOutputHeaders; BHttpResult fResult; // Request state/events diff --git a/src/kits/network/libnetapi/HttpRequest.cpp b/src/kits/network/libnetapi/HttpRequest.cpp index 5fb393b..6e9c431 100644 --- a/src/kits/network/libnetapi/HttpRequest.cpp +++ b/src/kits/network/libnetapi/HttpRequest.cpp @@ -317,7 +317,6 @@ BHttpRequest::_ProtocolLoop() newRequest = false; // Result reset - fOutputHeaders.Clear(); fHeaders.Clear(); _ResultHeaders().Clear(); @@ -487,6 +486,8 @@ BHttpRequest::_MakeRequest() _SendPostData(); fRequestStatus = kRequestInitialState; + + // Receive loop bool receiveEnd = false; bool parseEnd = false; @@ -507,8 +508,8 @@ BHttpRequest::_MakeRequest() while (!fQuit && !(receiveEnd && parseEnd)) { if (!receiveEnd) { fSocket->WaitForReadable(); - BNetBuffer chunk(kHttpBufferSize); - bytesRead = fSocket->Read(chunk.Data(), kHttpBufferSize); + BStackOrHeapArray<char, 4096> chunk(kHttpBufferSize); + bytesRead = fSocket->Read(chunk, kHttpBufferSize); if (bytesRead < 0) { readError = bytesRead; @@ -516,7 +517,7 @@ BHttpRequest::_MakeRequest() } else if (bytesRead == 0) receiveEnd = true; - fInputBuffer.AppendData(chunk.Data(), bytesRead); + fInputBuffer.AppendData(chunk, bytesRead); } else bytesRead = 0; @@ -677,7 +678,11 @@ BHttpRequest::_MakeRequest() if (decompress && receiveEnd) { readError = decompressingStream->Flush(); - if (readError != B_OK && readError != B_BUFFER_OVERFLOW) + + if (readError == B_BUFFER_OVERFLOW) + readError = B_OK; + + if (readError != B_OK) break; ssize_t size = decompressorStorage.Size(); @@ -813,31 +818,33 @@ BHttpRequest::_SendRequest() void BHttpRequest::_SendHeaders() { + BHttpHeaders outputHeaders; + // HTTP 1.1 additional headers if (fHttpVersion == B_HTTP_11) { BString host = Url().Host(); if (Url().HasPort() && !_IsDefaultPort()) host << ':' << Url().Port(); - fOutputHeaders.AddHeader("Host", host); + outputHeaders.AddHeader("Host", host); - fOutputHeaders.AddHeader("Accept", "*/*"); - fOutputHeaders.AddHeader("Accept-Encoding", "gzip,deflate"); + outputHeaders.AddHeader("Accept", "*/*"); + outputHeaders.AddHeader("Accept-Encoding", "gzip,deflate"); // Allow the remote server to send dynamic content by chunks // rather than waiting for the full content to be generated and // sending us data. - fOutputHeaders.AddHeader("Connection", "close"); + outputHeaders.AddHeader("Connection", "close"); // Let the remote server close the connection after response since // we don't handle multiple request on a single connection } // Classic HTTP headers if (fOptUserAgent.CountChars() > 0) - fOutputHeaders.AddHeader("User-Agent", fOptUserAgent.String()); + outputHeaders.AddHeader("User-Agent", fOptUserAgent.String()); if (fOptReferer.CountChars() > 0) - fOutputHeaders.AddHeader("Referer", fOptReferer.String()); + outputHeaders.AddHeader("Referer", fOptReferer.String()); // Authentication if (fContext != NULL) { @@ -849,7 +856,7 @@ BHttpRequest::_SendHeaders() } BString request(fRequestMethod); - fOutputHeaders.AddHeader("Authorization", + outputHeaders.AddHeader("Authorization", authentication.Authorization(fUrl, request)); } } @@ -869,16 +876,16 @@ BHttpRequest::_SendHeaders() break; } - fOutputHeaders.AddHeader("Content-Type", contentType); - fOutputHeaders.AddHeader("Content-Length", + outputHeaders.AddHeader("Content-Type", contentType); + outputHeaders.AddHeader("Content-Length", fOptPostFields->ContentLength()); } else if (fOptInputData != NULL && (fRequestMethod == B_HTTP_POST || fRequestMethod == B_HTTP_PUT)) { if (fOptInputDataSize >= 0) - fOutputHeaders.AddHeader("Content-Length", fOptInputDataSize); + outputHeaders.AddHeader("Content-Length", fOptInputDataSize); else - fOutputHeaders.AddHeader("Transfer-Encoding", "chunked"); + outputHeaders.AddHeader("Transfer-Encoding", "chunked"); } // Optional headers specified by the user @@ -886,14 +893,14 @@ BHttpRequest::_SendHeaders() for (int32 headerIndex = 0; headerIndex < fOptHeaders->CountHeaders(); headerIndex++) { BHttpHeader& optHeader = (*fOptHeaders)[headerIndex]; - int32 replaceIndex = fOutputHeaders.HasHeader(optHeader.Name()); + int32 replaceIndex = outputHeaders.HasHeader(optHeader.Name()); // Add or replace the current option header to the // output header list if (replaceIndex == -1) - fOutputHeaders.AddHeader(optHeader.Name(), optHeader.Value()); + outputHeaders.AddHeader(optHeader.Name(), optHeader.Value()); else - fOutputHeaders[replaceIndex].SetValue(optHeader.Value()); + outputHeaders[replaceIndex].SetValue(optHeader.Value()); } } @@ -913,16 +920,16 @@ BHttpRequest::_SendHeaders() cookieString << "; "; } - fOutputHeaders.AddHeader("Cookie", cookieString); + outputHeaders.AddHeader("Cookie", cookieString); } } // Write output headers to output stream BString headerData; - for (int32 headerIndex = 0; headerIndex < fOutputHeaders.CountHeaders(); + for (int32 headerIndex = 0; headerIndex < outputHeaders.CountHeaders(); headerIndex++) { - const char* header = fOutputHeaders.HeaderAt(headerIndex).Header(); + const char* header = outputHeaders.HeaderAt(headerIndex).Header(); headerData << header; headerData << "\r\n";