Skip to content

Commit

Permalink
fix(HTTPClientSession): not working with UNIX_LOCAL SocketAddress #2578
Browse files Browse the repository at this point in the history
  • Loading branch information
aleks-f committed Nov 25, 2023
1 parent f8faf69 commit b3ab168
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Net/include/Poco/Net/HTTPClientSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ class Net_API HTTPClientSession: public HTTPSession
HTTPBasicCredentials _proxyBasicCreds;
HTTPDigestCredentials _proxyDigestCreds;
HTTPNTLMCredentials _proxyNTLMCreds;
bool _ntlmProxyAuthenticated;
bool _ntlmProxyAuthenticated = false;

static ProxyConfig _globalProxyConfig;

Expand Down
3 changes: 3 additions & 0 deletions Net/include/Poco/Net/SocketAddress.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ class Net_API SocketAddress
/// Maximum length in bytes of a socket address.
};

static bool isUnixLocal(const std::string& hostAndPort);
/// Returns true iff `hostAndPort` is an absolute file path.

protected:
void init(const IPAddress& hostAddress, Poco::UInt16 portNumber);
void init(const std::string& hostAddress, Poco::UInt16 portNumber);
Expand Down
7 changes: 6 additions & 1 deletion Net/src/HTTPClientSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,12 @@ void HTTPClientSession::reconnect()
{
SocketAddress addr;
if (_proxyConfig.host.empty() || bypassProxy())
addr = SocketAddress(_host, _port);
{
if (SocketAddress::isUnixLocal(_host))
addr = SocketAddress(_host);
else
addr = SocketAddress(_host, _port);
}
else
addr = SocketAddress(_proxyConfig.host, _proxyConfig.port);

Expand Down
3 changes: 2 additions & 1 deletion Net/src/HTTPSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ void HTTPSession::connect(const SocketAddress& address)
_socket.connect(address, _connectionTimeout);
_socket.setReceiveTimeout(_receiveTimeout);
_socket.setSendTimeout(_sendTimeout);
_socket.setNoDelay(true);
if (address.family() != SocketAddress::UNIX_LOCAL)
_socket.setNoDelay(true);
// There may be leftover data from a previous (failed) request in the buffer,
// so we clear it.
_pCurrent = _pEnd = _pBuffer;
Expand Down
29 changes: 16 additions & 13 deletions Net/src/SocketAddress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ SocketAddress::SocketAddress()

SocketAddress::SocketAddress(Family fam)
{
init(IPAddress(fam), 0);
init(IPAddress(fam), 0);
}


Expand Down Expand Up @@ -362,31 +362,34 @@ void SocketAddress::init(Family fam, const std::string& address)
}


bool SocketAddress::isUnixLocal(const std::string& hostAndPort)
{
#if defined(POCO_HAS_UNIX_SOCKET)
#if defined(POCO_OS_FAMILY_WINDOWS)
RegularExpression re(R"((?:[a-zA-Z]\:|\\\\[\w\s\.]+\\[\w\s\.$]+)\\(?:[\w\s\.]+\\)*[\w\s\.]*?$)");
if (re.match(hostAndPort)) return true;
#elif defined(POCO_OS_FAMILY_UNIX)
if (hostAndPort.size() && (hostAndPort[0] == '/')) return true;
#endif
#endif
return false;
}


void SocketAddress::init(const std::string& hostAndPort)
{
poco_assert (!hostAndPort.empty());

#if defined(POCO_OS_FAMILY_WINDOWS) && defined(POCO_HAS_UNIX_SOCKET)
RegularExpression re(R"((?:[a-zA-Z]\:|\\\\[\w\s\.]+\\[\w\s\.$]+)\\(?:[\w\s\.]+\\)*[\w\s\.]*?$)");
if (re.match(hostAndPort))
if (isUnixLocal(hostAndPort))
{
newLocal(hostAndPort);
return;
}
#endif

std::string host;
std::string port;
std::string::const_iterator it = hostAndPort.begin();
std::string::const_iterator end = hostAndPort.end();

#if defined(POCO_OS_FAMILY_UNIX)
if (*it == '/')
{
newLocal(hostAndPort);
return;
}
#endif
if (*it == '[')
{
++it;
Expand Down
31 changes: 31 additions & 0 deletions Net/testsuite/src/HTTPClientSessionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/StreamCopier.h"
#include "Poco/File.h"
#include "Poco/Path.h"
#include "HTTPTestServer.h"
#include <istream>
#include <ostream>
Expand All @@ -26,6 +28,8 @@ using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPMessage;
using Poco::StreamCopier;
using Poco::File;
using Poco::Path;


HTTPClientSessionTest::HTTPClientSessionTest(const std::string& name): CppUnit::TestCase(name)
Expand Down Expand Up @@ -54,6 +58,32 @@ void HTTPClientSessionTest::testGetSmall()
}


void HTTPClientSessionTest::testGetSmallUnix()
{
#if defined(POCO_HAS_UNIX_SOCKET)
#if POCO_OS == POCO_OS_ANDROID
File socketFile("/data/local/tmp/SocketTest.sock");
#elif defined(POCO_OS_FAMILY_WINDOWS)
File socketFile(Path::tempHome() + "SocketTest.sock");
#else
File socketFile("/tmp/SocketTest.sock");
#endif // POCO_OS == POCO_OS_ANDROID
if (socketFile.exists()) socketFile.remove();
HTTPTestServer srv(socketFile.path());
HTTPClientSession s(socketFile.path());
HTTPRequest request(HTTPRequest::HTTP_GET, "/small");
s.sendRequest(request);
HTTPResponse response;
std::istream& rs = s.receiveResponse(response);
assertTrue(response.getContentLength() == HTTPTestServer::SMALL_BODY.length());
assertTrue(response.getContentType() == "text/plain");
std::ostringstream ostr;
StreamCopier::copyStream(rs, ostr);
assertTrue(ostr.str() == HTTPTestServer::SMALL_BODY);
#endif // POCO_HAS_UNIX_SOCKET
}


void HTTPClientSessionTest::testGetLarge()
{
HTTPTestServer srv;
Expand Down Expand Up @@ -373,6 +403,7 @@ CppUnit::Test* HTTPClientSessionTest::suite()
CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("HTTPClientSessionTest");

CppUnit_addTest(pSuite, HTTPClientSessionTest, testGetSmall);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testGetSmallUnix);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testGetLarge);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testHead);
CppUnit_addTest(pSuite, HTTPClientSessionTest, testPostSmallIdentity);
Expand Down
1 change: 1 addition & 0 deletions Net/testsuite/src/HTTPClientSessionTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class HTTPClientSessionTest: public CppUnit::TestCase
~HTTPClientSessionTest();

void testGetSmall();
void testGetSmallUnix();
void testGetLarge();
void testHead();
void testPostSmallIdentity();
Expand Down
17 changes: 15 additions & 2 deletions Net/testsuite/src/HTTPTestServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ HTTPTestServer::HTTPTestServer():
}


HTTPTestServer::HTTPTestServer(const std::string& addr) :
_socket(SocketAddress(addr)),
_thread("HTTPTestServer"),
_stop(false)
{
_thread.start(*this);
_ready.wait();
_lastRequest.reserve(4000);
}


HTTPTestServer::~HTTPTestServer()
{
_stop = true;
Expand Down Expand Up @@ -74,13 +85,15 @@ void HTTPTestServer::run()
{
_lastRequest.append(buffer, n);
if (!requestComplete())
{
n = ss.receiveBytes(buffer, sizeof(buffer));
}
else
n = 0;
}
std::string response = handleRequest();
ss.sendBytes(response.data(), (int) response.size());
Poco::Thread::sleep(1000);
n = ss.sendBytes(response.data(), (int) response.size());
if (n) Poco::Thread::sleep(1000);
try
{
ss.shutdown();
Expand Down
3 changes: 3 additions & 0 deletions Net/testsuite/src/HTTPTestServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class HTTPTestServer: public Poco::Runnable
HTTPTestServer();
/// Creates the HTTPTestServer.

HTTPTestServer(const std::string& addr);
/// Creates the HTTPTestServer on the specified address.

~HTTPTestServer();
/// Destroys the HTTPTestServer.

Expand Down

0 comments on commit b3ab168

Please sign in to comment.