summaryrefslogtreecommitdiffstats
path: root/contrib/libs/poco/Net/src/HTTPClientSession.cpp
diff options
context:
space:
mode:
authororivej <[email protected]>2022-02-10 16:44:49 +0300
committerDaniil Cherednik <[email protected]>2022-02-10 16:44:49 +0300
commit718c552901d703c502ccbefdfc3c9028d608b947 (patch)
tree46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/poco/Net/src/HTTPClientSession.cpp
parente9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff)
Restoring authorship annotation for <[email protected]>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/poco/Net/src/HTTPClientSession.cpp')
-rw-r--r--contrib/libs/poco/Net/src/HTTPClientSession.cpp940
1 files changed, 470 insertions, 470 deletions
diff --git a/contrib/libs/poco/Net/src/HTTPClientSession.cpp b/contrib/libs/poco/Net/src/HTTPClientSession.cpp
index c2b81703431..cca2808b1b8 100644
--- a/contrib/libs/poco/Net/src/HTTPClientSession.cpp
+++ b/contrib/libs/poco/Net/src/HTTPClientSession.cpp
@@ -1,470 +1,470 @@
-//
-// HTTPClientSession.cpp
-//
-// Library: Net
-// Package: HTTPClient
-// Module: HTTPClientSession
-//
-// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
-// and Contributors.
-//
-// SPDX-License-Identifier: BSL-1.0
-//
-
-
-#include "Poco/Net/HTTPClientSession.h"
-#include "Poco/Net/HTTPRequest.h"
-#include "Poco/Net/HTTPResponse.h"
-#include "Poco/Net/HTTPHeaderStream.h"
-#include "Poco/Net/HTTPStream.h"
-#include "Poco/Net/HTTPFixedLengthStream.h"
-#include "Poco/Net/HTTPChunkedStream.h"
-#include "Poco/Net/HTTPBasicCredentials.h"
-#include "Poco/Net/NetException.h"
-#include "Poco/NumberFormatter.h"
-#include "Poco/CountingStream.h"
-#include "Poco/RegularExpression.h"
-#include <sstream>
-
-
-using Poco::NumberFormatter;
-using Poco::IllegalStateException;
-
-
-namespace Poco {
-namespace Net {
-
-
-HTTPClientSession::ProxyConfig HTTPClientSession::_globalProxyConfig;
-
-
-HTTPClientSession::HTTPClientSession():
- _port(HTTPSession::HTTP_PORT),
- _proxyConfig(_globalProxyConfig),
- _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
- _reconnect(false),
- _mustReconnect(false),
- _expectResponseBody(false),
- _responseReceived(false)
-{
-}
-
-
-HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
- HTTPSession(socket),
- _port(HTTPSession::HTTP_PORT),
- _proxyConfig(_globalProxyConfig),
- _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
- _reconnect(false),
- _mustReconnect(false),
- _expectResponseBody(false),
- _responseReceived(false)
-{
-}
-
-
-HTTPClientSession::HTTPClientSession(const SocketAddress& address):
- _host(address.host().toString()),
- _port(address.port()),
- _proxyConfig(_globalProxyConfig),
- _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
- _reconnect(false),
- _mustReconnect(false),
- _expectResponseBody(false),
- _responseReceived(false)
-{
-}
-
-
-HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port):
- _host(host),
- _port(port),
- _proxyConfig(_globalProxyConfig),
- _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
- _reconnect(false),
- _mustReconnect(false),
- _expectResponseBody(false),
- _responseReceived(false)
-{
-}
-
-
-HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig):
- _host(host),
- _port(port),
- _proxyConfig(proxyConfig),
- _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
- _reconnect(false),
- _mustReconnect(false),
- _expectResponseBody(false),
- _responseReceived(false)
-{
-}
-
-
-HTTPClientSession::~HTTPClientSession()
-{
-}
-
-
-void HTTPClientSession::setHost(const std::string& host)
-{
- if (!connected())
- _host = host;
- else
- throw IllegalStateException("Cannot set the host for an already connected session");
-}
-
-
-void HTTPClientSession::setPort(Poco::UInt16 port)
-{
- if (!connected())
- _port = port;
- else
- throw IllegalStateException("Cannot set the port number for an already connected session");
-}
-
-
-void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port)
-{
- if (!connected())
- {
- _proxyConfig.host = host;
- _proxyConfig.port = port;
- }
- else throw IllegalStateException("Cannot set the proxy host and port for an already connected session");
-}
-
-
-void HTTPClientSession::setProxyHost(const std::string& host)
-{
- if (!connected())
- _proxyConfig.host = host;
- else
- throw IllegalStateException("Cannot set the proxy host for an already connected session");
-}
-
-
-void HTTPClientSession::setProxyPort(Poco::UInt16 port)
-{
- if (!connected())
- _proxyConfig.port = port;
- else
- throw IllegalStateException("Cannot set the proxy port number for an already connected session");
-}
-
-
-void HTTPClientSession::setProxyCredentials(const std::string& username, const std::string& password)
-{
- _proxyConfig.username = username;
- _proxyConfig.password = password;
-}
-
-
-void HTTPClientSession::setProxyUsername(const std::string& username)
-{
- _proxyConfig.username = username;
-}
-
-
-void HTTPClientSession::setProxyPassword(const std::string& password)
-{
- _proxyConfig.password = password;
-}
-
-
-void HTTPClientSession::setProxyConfig(const ProxyConfig& config)
-{
- _proxyConfig = config;
-}
-
-
-void HTTPClientSession::setGlobalProxyConfig(const ProxyConfig& config)
-{
- _globalProxyConfig = config;
-}
-
-
-void HTTPClientSession::setKeepAliveTimeout(const Poco::Timespan& timeout)
-{
- _keepAliveTimeout = timeout;
-}
-
-
-std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
-{
- _pRequestStream = 0;
- _pResponseStream = 0;
- clearException();
- _responseReceived = false;
-
- bool keepAlive = getKeepAlive();
- if (((connected() && !keepAlive) || mustReconnect()) && !_host.empty())
- {
- close();
- _mustReconnect = false;
- }
- try
- {
- if (!connected())
- reconnect();
- if (!keepAlive)
- request.setKeepAlive(false);
- if (!request.has(HTTPRequest::HOST) && !_host.empty())
- request.setHost(_host, _port);
- if (!_proxyConfig.host.empty() && !bypassProxy())
- {
- request.setURI(proxyRequestPrefix() + request.getURI());
- proxyAuthenticate(request);
- }
- _reconnect = keepAlive;
- _expectResponseBody = request.getMethod() != HTTPRequest::HTTP_HEAD;
- const std::string& method = request.getMethod();
- if (request.getChunkedTransferEncoding())
- {
- HTTPHeaderOutputStream hos(*this);
- request.write(hos);
- _pRequestStream = new HTTPChunkedOutputStream(*this);
- }
- else if (request.hasContentLength())
- {
- Poco::CountingOutputStream cs;
- request.write(cs);
-#if POCO_HAVE_INT64
- _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength64() + cs.chars());
-#else
- _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength() + cs.chars());
-#endif
- request.write(*_pRequestStream);
- }
- else if ((method != HTTPRequest::HTTP_PUT && method != HTTPRequest::HTTP_POST && method != HTTPRequest::HTTP_PATCH) || request.has(HTTPRequest::UPGRADE))
- {
- Poco::CountingOutputStream cs;
- request.write(cs);
- _pRequestStream = new HTTPFixedLengthOutputStream(*this, cs.chars());
- request.write(*_pRequestStream);
- }
- else
- {
- _pRequestStream = new HTTPOutputStream(*this);
- request.write(*_pRequestStream);
- }
- _lastRequest.update();
- return *_pRequestStream;
- }
- catch (Exception&)
- {
- close();
- throw;
- }
-}
-
-
-void HTTPClientSession::flushRequest()
-{
- _pRequestStream = 0;
- if (networkException()) networkException()->rethrow();
-}
-
-
-std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
-{
- flushRequest();
- if (!_responseReceived)
- {
- do
- {
- response.clear();
- HTTPHeaderInputStream his(*this);
- try
- {
- response.read(his);
- }
- catch (Exception&)
- {
- close();
- if (networkException())
- networkException()->rethrow();
- else
- throw;
- throw;
- }
- }
- while (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
- }
-
- _mustReconnect = getKeepAlive() && !response.getKeepAlive();
-
- if (!_expectResponseBody || response.getStatus() < 200 || response.getStatus() == HTTPResponse::HTTP_NO_CONTENT || response.getStatus() == HTTPResponse::HTTP_NOT_MODIFIED)
- _pResponseStream = new HTTPFixedLengthInputStream(*this, 0);
- else if (response.getChunkedTransferEncoding())
- _pResponseStream = new HTTPChunkedInputStream(*this);
- else if (response.hasContentLength())
-#if defined(POCO_HAVE_INT64)
- _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength64());
-#else
- _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength());
-#endif
- else
- _pResponseStream = new HTTPInputStream(*this);
-
- return *_pResponseStream;
-}
-
-
-bool HTTPClientSession::peekResponse(HTTPResponse& response)
-{
- poco_assert (!_responseReceived);
-
- _pRequestStream->flush();
-
- if (networkException()) networkException()->rethrow();
-
- response.clear();
- HTTPHeaderInputStream his(*this);
- try
- {
- response.read(his);
- }
- catch (Exception&)
- {
- close();
- if (networkException())
- networkException()->rethrow();
- else
- throw;
- throw;
- }
- _responseReceived = response.getStatus() != HTTPResponse::HTTP_CONTINUE;
- return !_responseReceived;
-}
-
-
-void HTTPClientSession::reset()
-{
- close();
-}
-
-
-bool HTTPClientSession::secure() const
-{
- return false;
-}
-
-
-int HTTPClientSession::write(const char* buffer, std::streamsize length)
-{
- try
- {
- int rc = HTTPSession::write(buffer, length);
- _reconnect = false;
- return rc;
- }
- catch (IOException&)
- {
- if (_reconnect)
- {
- close();
- reconnect();
- int rc = HTTPSession::write(buffer, length);
- clearException();
- _reconnect = false;
- return rc;
- }
- else throw;
- }
-}
-
-
-void HTTPClientSession::reconnect()
-{
- if (_proxyConfig.host.empty() || bypassProxy())
- {
- SocketAddress addr(_host, _port);
- connect(addr);
- }
- else
- {
- SocketAddress addr(_proxyConfig.host, _proxyConfig.port);
- connect(addr);
- }
-}
-
-
-std::string HTTPClientSession::proxyRequestPrefix() const
-{
- std::string result("http://");
- result.append(_host);
- result.append(":");
- NumberFormatter::append(result, _port);
- return result;
-}
-
-
-bool HTTPClientSession::mustReconnect() const
-{
- if (!_mustReconnect)
- {
- Poco::Timestamp now;
- return _keepAliveTimeout <= now - _lastRequest;
- }
- else return true;
-}
-
-
-void HTTPClientSession::proxyAuthenticate(HTTPRequest& request)
-{
- proxyAuthenticateImpl(request);
-}
-
-
-void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request)
-{
- if (!_proxyConfig.username.empty())
- {
- HTTPBasicCredentials creds(_proxyConfig.username, _proxyConfig.password);
- creds.proxyAuthenticate(request);
- }
-}
-
-
-StreamSocket HTTPClientSession::proxyConnect()
-{
- ProxyConfig emptyProxyConfig;
- HTTPClientSession proxySession(getProxyHost(), getProxyPort(), emptyProxyConfig);
- proxySession.setTimeout(getTimeout());
- std::string targetAddress(_host);
- targetAddress.append(":");
- NumberFormatter::append(targetAddress, _port);
- HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress, HTTPMessage::HTTP_1_1);
- HTTPResponse proxyResponse;
- proxyRequest.set("Proxy-Connection", "keep-alive");
- proxyRequest.set("Host", getHost());
- proxyAuthenticateImpl(proxyRequest);
- proxySession.setKeepAlive(true);
- proxySession.sendRequest(proxyRequest);
- proxySession.receiveResponse(proxyResponse);
- if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK)
- throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason());
- return proxySession.detachSocket();
-}
-
-
-void HTTPClientSession::proxyTunnel()
-{
- StreamSocket ss = proxyConnect();
- attachSocket(ss);
-}
-
-
-bool HTTPClientSession::bypassProxy() const
-{
- if (!_proxyConfig.nonProxyHosts.empty())
- {
- return RegularExpression::match(_host, _proxyConfig.nonProxyHosts, RegularExpression::RE_CASELESS | RegularExpression::RE_ANCHORED);
- }
- else return false;
-}
-
-
-} } // namespace Poco::Net
+//
+// HTTPClientSession.cpp
+//
+// Library: Net
+// Package: HTTPClient
+// Module: HTTPClientSession
+//
+// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
+// and Contributors.
+//
+// SPDX-License-Identifier: BSL-1.0
+//
+
+
+#include "Poco/Net/HTTPClientSession.h"
+#include "Poco/Net/HTTPRequest.h"
+#include "Poco/Net/HTTPResponse.h"
+#include "Poco/Net/HTTPHeaderStream.h"
+#include "Poco/Net/HTTPStream.h"
+#include "Poco/Net/HTTPFixedLengthStream.h"
+#include "Poco/Net/HTTPChunkedStream.h"
+#include "Poco/Net/HTTPBasicCredentials.h"
+#include "Poco/Net/NetException.h"
+#include "Poco/NumberFormatter.h"
+#include "Poco/CountingStream.h"
+#include "Poco/RegularExpression.h"
+#include <sstream>
+
+
+using Poco::NumberFormatter;
+using Poco::IllegalStateException;
+
+
+namespace Poco {
+namespace Net {
+
+
+HTTPClientSession::ProxyConfig HTTPClientSession::_globalProxyConfig;
+
+
+HTTPClientSession::HTTPClientSession():
+ _port(HTTPSession::HTTP_PORT),
+ _proxyConfig(_globalProxyConfig),
+ _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
+ _reconnect(false),
+ _mustReconnect(false),
+ _expectResponseBody(false),
+ _responseReceived(false)
+{
+}
+
+
+HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
+ HTTPSession(socket),
+ _port(HTTPSession::HTTP_PORT),
+ _proxyConfig(_globalProxyConfig),
+ _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
+ _reconnect(false),
+ _mustReconnect(false),
+ _expectResponseBody(false),
+ _responseReceived(false)
+{
+}
+
+
+HTTPClientSession::HTTPClientSession(const SocketAddress& address):
+ _host(address.host().toString()),
+ _port(address.port()),
+ _proxyConfig(_globalProxyConfig),
+ _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
+ _reconnect(false),
+ _mustReconnect(false),
+ _expectResponseBody(false),
+ _responseReceived(false)
+{
+}
+
+
+HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port):
+ _host(host),
+ _port(port),
+ _proxyConfig(_globalProxyConfig),
+ _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
+ _reconnect(false),
+ _mustReconnect(false),
+ _expectResponseBody(false),
+ _responseReceived(false)
+{
+}
+
+
+HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig):
+ _host(host),
+ _port(port),
+ _proxyConfig(proxyConfig),
+ _keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
+ _reconnect(false),
+ _mustReconnect(false),
+ _expectResponseBody(false),
+ _responseReceived(false)
+{
+}
+
+
+HTTPClientSession::~HTTPClientSession()
+{
+}
+
+
+void HTTPClientSession::setHost(const std::string& host)
+{
+ if (!connected())
+ _host = host;
+ else
+ throw IllegalStateException("Cannot set the host for an already connected session");
+}
+
+
+void HTTPClientSession::setPort(Poco::UInt16 port)
+{
+ if (!connected())
+ _port = port;
+ else
+ throw IllegalStateException("Cannot set the port number for an already connected session");
+}
+
+
+void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port)
+{
+ if (!connected())
+ {
+ _proxyConfig.host = host;
+ _proxyConfig.port = port;
+ }
+ else throw IllegalStateException("Cannot set the proxy host and port for an already connected session");
+}
+
+
+void HTTPClientSession::setProxyHost(const std::string& host)
+{
+ if (!connected())
+ _proxyConfig.host = host;
+ else
+ throw IllegalStateException("Cannot set the proxy host for an already connected session");
+}
+
+
+void HTTPClientSession::setProxyPort(Poco::UInt16 port)
+{
+ if (!connected())
+ _proxyConfig.port = port;
+ else
+ throw IllegalStateException("Cannot set the proxy port number for an already connected session");
+}
+
+
+void HTTPClientSession::setProxyCredentials(const std::string& username, const std::string& password)
+{
+ _proxyConfig.username = username;
+ _proxyConfig.password = password;
+}
+
+
+void HTTPClientSession::setProxyUsername(const std::string& username)
+{
+ _proxyConfig.username = username;
+}
+
+
+void HTTPClientSession::setProxyPassword(const std::string& password)
+{
+ _proxyConfig.password = password;
+}
+
+
+void HTTPClientSession::setProxyConfig(const ProxyConfig& config)
+{
+ _proxyConfig = config;
+}
+
+
+void HTTPClientSession::setGlobalProxyConfig(const ProxyConfig& config)
+{
+ _globalProxyConfig = config;
+}
+
+
+void HTTPClientSession::setKeepAliveTimeout(const Poco::Timespan& timeout)
+{
+ _keepAliveTimeout = timeout;
+}
+
+
+std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
+{
+ _pRequestStream = 0;
+ _pResponseStream = 0;
+ clearException();
+ _responseReceived = false;
+
+ bool keepAlive = getKeepAlive();
+ if (((connected() && !keepAlive) || mustReconnect()) && !_host.empty())
+ {
+ close();
+ _mustReconnect = false;
+ }
+ try
+ {
+ if (!connected())
+ reconnect();
+ if (!keepAlive)
+ request.setKeepAlive(false);
+ if (!request.has(HTTPRequest::HOST) && !_host.empty())
+ request.setHost(_host, _port);
+ if (!_proxyConfig.host.empty() && !bypassProxy())
+ {
+ request.setURI(proxyRequestPrefix() + request.getURI());
+ proxyAuthenticate(request);
+ }
+ _reconnect = keepAlive;
+ _expectResponseBody = request.getMethod() != HTTPRequest::HTTP_HEAD;
+ const std::string& method = request.getMethod();
+ if (request.getChunkedTransferEncoding())
+ {
+ HTTPHeaderOutputStream hos(*this);
+ request.write(hos);
+ _pRequestStream = new HTTPChunkedOutputStream(*this);
+ }
+ else if (request.hasContentLength())
+ {
+ Poco::CountingOutputStream cs;
+ request.write(cs);
+#if POCO_HAVE_INT64
+ _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength64() + cs.chars());
+#else
+ _pRequestStream = new HTTPFixedLengthOutputStream(*this, request.getContentLength() + cs.chars());
+#endif
+ request.write(*_pRequestStream);
+ }
+ else if ((method != HTTPRequest::HTTP_PUT && method != HTTPRequest::HTTP_POST && method != HTTPRequest::HTTP_PATCH) || request.has(HTTPRequest::UPGRADE))
+ {
+ Poco::CountingOutputStream cs;
+ request.write(cs);
+ _pRequestStream = new HTTPFixedLengthOutputStream(*this, cs.chars());
+ request.write(*_pRequestStream);
+ }
+ else
+ {
+ _pRequestStream = new HTTPOutputStream(*this);
+ request.write(*_pRequestStream);
+ }
+ _lastRequest.update();
+ return *_pRequestStream;
+ }
+ catch (Exception&)
+ {
+ close();
+ throw;
+ }
+}
+
+
+void HTTPClientSession::flushRequest()
+{
+ _pRequestStream = 0;
+ if (networkException()) networkException()->rethrow();
+}
+
+
+std::istream& HTTPClientSession::receiveResponse(HTTPResponse& response)
+{
+ flushRequest();
+ if (!_responseReceived)
+ {
+ do
+ {
+ response.clear();
+ HTTPHeaderInputStream his(*this);
+ try
+ {
+ response.read(his);
+ }
+ catch (Exception&)
+ {
+ close();
+ if (networkException())
+ networkException()->rethrow();
+ else
+ throw;
+ throw;
+ }
+ }
+ while (response.getStatus() == HTTPResponse::HTTP_CONTINUE);
+ }
+
+ _mustReconnect = getKeepAlive() && !response.getKeepAlive();
+
+ if (!_expectResponseBody || response.getStatus() < 200 || response.getStatus() == HTTPResponse::HTTP_NO_CONTENT || response.getStatus() == HTTPResponse::HTTP_NOT_MODIFIED)
+ _pResponseStream = new HTTPFixedLengthInputStream(*this, 0);
+ else if (response.getChunkedTransferEncoding())
+ _pResponseStream = new HTTPChunkedInputStream(*this);
+ else if (response.hasContentLength())
+#if defined(POCO_HAVE_INT64)
+ _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength64());
+#else
+ _pResponseStream = new HTTPFixedLengthInputStream(*this, response.getContentLength());
+#endif
+ else
+ _pResponseStream = new HTTPInputStream(*this);
+
+ return *_pResponseStream;
+}
+
+
+bool HTTPClientSession::peekResponse(HTTPResponse& response)
+{
+ poco_assert (!_responseReceived);
+
+ _pRequestStream->flush();
+
+ if (networkException()) networkException()->rethrow();
+
+ response.clear();
+ HTTPHeaderInputStream his(*this);
+ try
+ {
+ response.read(his);
+ }
+ catch (Exception&)
+ {
+ close();
+ if (networkException())
+ networkException()->rethrow();
+ else
+ throw;
+ throw;
+ }
+ _responseReceived = response.getStatus() != HTTPResponse::HTTP_CONTINUE;
+ return !_responseReceived;
+}
+
+
+void HTTPClientSession::reset()
+{
+ close();
+}
+
+
+bool HTTPClientSession::secure() const
+{
+ return false;
+}
+
+
+int HTTPClientSession::write(const char* buffer, std::streamsize length)
+{
+ try
+ {
+ int rc = HTTPSession::write(buffer, length);
+ _reconnect = false;
+ return rc;
+ }
+ catch (IOException&)
+ {
+ if (_reconnect)
+ {
+ close();
+ reconnect();
+ int rc = HTTPSession::write(buffer, length);
+ clearException();
+ _reconnect = false;
+ return rc;
+ }
+ else throw;
+ }
+}
+
+
+void HTTPClientSession::reconnect()
+{
+ if (_proxyConfig.host.empty() || bypassProxy())
+ {
+ SocketAddress addr(_host, _port);
+ connect(addr);
+ }
+ else
+ {
+ SocketAddress addr(_proxyConfig.host, _proxyConfig.port);
+ connect(addr);
+ }
+}
+
+
+std::string HTTPClientSession::proxyRequestPrefix() const
+{
+ std::string result("http://");
+ result.append(_host);
+ result.append(":");
+ NumberFormatter::append(result, _port);
+ return result;
+}
+
+
+bool HTTPClientSession::mustReconnect() const
+{
+ if (!_mustReconnect)
+ {
+ Poco::Timestamp now;
+ return _keepAliveTimeout <= now - _lastRequest;
+ }
+ else return true;
+}
+
+
+void HTTPClientSession::proxyAuthenticate(HTTPRequest& request)
+{
+ proxyAuthenticateImpl(request);
+}
+
+
+void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request)
+{
+ if (!_proxyConfig.username.empty())
+ {
+ HTTPBasicCredentials creds(_proxyConfig.username, _proxyConfig.password);
+ creds.proxyAuthenticate(request);
+ }
+}
+
+
+StreamSocket HTTPClientSession::proxyConnect()
+{
+ ProxyConfig emptyProxyConfig;
+ HTTPClientSession proxySession(getProxyHost(), getProxyPort(), emptyProxyConfig);
+ proxySession.setTimeout(getTimeout());
+ std::string targetAddress(_host);
+ targetAddress.append(":");
+ NumberFormatter::append(targetAddress, _port);
+ HTTPRequest proxyRequest(HTTPRequest::HTTP_CONNECT, targetAddress, HTTPMessage::HTTP_1_1);
+ HTTPResponse proxyResponse;
+ proxyRequest.set("Proxy-Connection", "keep-alive");
+ proxyRequest.set("Host", getHost());
+ proxyAuthenticateImpl(proxyRequest);
+ proxySession.setKeepAlive(true);
+ proxySession.sendRequest(proxyRequest);
+ proxySession.receiveResponse(proxyResponse);
+ if (proxyResponse.getStatus() != HTTPResponse::HTTP_OK)
+ throw HTTPException("Cannot establish proxy connection", proxyResponse.getReason());
+ return proxySession.detachSocket();
+}
+
+
+void HTTPClientSession::proxyTunnel()
+{
+ StreamSocket ss = proxyConnect();
+ attachSocket(ss);
+}
+
+
+bool HTTPClientSession::bypassProxy() const
+{
+ if (!_proxyConfig.nonProxyHosts.empty())
+ {
+ return RegularExpression::match(_host, _proxyConfig.nonProxyHosts, RegularExpression::RE_CASELESS | RegularExpression::RE_ANCHORED);
+ }
+ else return false;
+}
+
+
+} } // namespace Poco::Net