Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions Net/include/Poco/Net/HTTPClientSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "Poco/Net/HTTPBasicCredentials.h"
#include "Poco/Net/HTTPDigestCredentials.h"
#include "Poco/Net/HTTPNTLMCredentials.h"
#include "Poco/Net/HTTPSessionFactory.h"
#include "Poco/Net/SocketAddress.h"
#include "Poco/SharedPtr.h"
#include <istream>
Expand Down Expand Up @@ -78,14 +79,21 @@ class Net_API HTTPClientSession: public HTTPSession
{
ProxyConfig():
port(HTTP_PORT),
authMethod(PROXY_AUTH_HTTP_BASIC)
authMethod(PROXY_AUTH_HTTP_BASIC),
protocol("http"),
tunnel(true)
{
}

std::string host;
/// Proxy server host name or IP address.
Poco::UInt16 port;
/// Proxy server TCP port.
std::string protocol;
/// Protocol to use (http or https).
bool tunnel;
/// Use proxy as tunnel (establish 2-way communication through CONNECT request).
/// If tunnel option is 'false' request will be send directly to proxy without CONNECT request.
std::string username;
/// Proxy server username.
std::string password;
Expand Down Expand Up @@ -138,21 +146,33 @@ class Net_API HTTPClientSession: public HTTPSession
Poco::UInt16 getPort() const;
/// Returns the port number of the target HTTP server.

void setProxy(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT);
/// Sets the proxy host name and port number.
void setProxy(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT, const std::string& protocol = "http", bool tunnel = true);
/// Sets the proxy host name, port number, protocol (http or https) and tunnel behaviour.

void setProxyHost(const std::string& host);
/// Sets the host name of the proxy server.

void setProxyPort(Poco::UInt16 port);
/// Sets the port number of the proxy server.

void setProxyProtocol(const std::string& protocol);
/// Sets the proxy protocol (http or https).

void setProxyTunnel(bool tunnel);
/// If 'true' proxy will be used as tunnel.

const std::string& getProxyHost() const;
/// Returns the proxy host name.

Poco::UInt16 getProxyPort() const;
/// Returns the proxy port number.

const std::string& getProxyProtocol() const;
/// Returns the proxy protocol.

bool isProxyTunnel() const;
/// Returns 'true' if proxy is configured as tunnel.

void setProxyCredentials(const std::string& username, const std::string& password);
/// Sets the username and password for proxy authentication.
/// Only Basic authentication is supported.
Expand Down Expand Up @@ -334,6 +354,8 @@ class Net_API HTTPClientSession: public HTTPSession
/// Calls proxyConnect() and attaches the resulting StreamSocket
/// to the HTTPClientSession.

HTTPSessionFactory _proxySessionFactory;
/// Factory to create HTTPClientSession to proxy.
private:
std::string _host;
Poco::UInt16 _port;
Expand Down Expand Up @@ -387,6 +409,18 @@ inline Poco::UInt16 HTTPClientSession::getProxyPort() const
}


inline const std::string& HTTPClientSession::getProxyProtocol() const
{
return _proxyConfig.protocol;
}


inline bool HTTPClientSession::isProxyTunnel() const
{
return _proxyConfig.tunnel;
}


inline const std::string& HTTPClientSession::getProxyUsername() const
{
return _proxyConfig.username;
Expand Down
60 changes: 49 additions & 11 deletions Net/src/HTTPClientSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@


#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPSessionInstantiator.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPHeaderStream.h"
Expand Down Expand Up @@ -48,6 +49,7 @@ HTTPClientSession::HTTPClientSession():
_responseReceived(false),
_ntlmProxyAuthenticated(false)
{
_proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator);
}


Expand All @@ -62,6 +64,7 @@ HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
_responseReceived(false),
_ntlmProxyAuthenticated(false)
{
_proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator);
}


Expand All @@ -76,6 +79,7 @@ HTTPClientSession::HTTPClientSession(const SocketAddress& address):
_responseReceived(false),
_ntlmProxyAuthenticated(false)
{
_proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator);
}


Expand All @@ -90,6 +94,7 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port)
_responseReceived(false),
_ntlmProxyAuthenticated(false)
{
_proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator);
}


Expand All @@ -104,11 +109,13 @@ HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port,
_responseReceived(false),
_ntlmProxyAuthenticated(false)
{
_proxySessionFactory.registerProtocol("http", new HTTPSessionInstantiator);
}


HTTPClientSession::~HTTPClientSession()
{
_proxySessionFactory.unregisterProtocol("http");
}


Expand All @@ -130,14 +137,19 @@ void HTTPClientSession::setPort(Poco::UInt16 port)
}


void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port)
void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port, const std::string& protocol, bool tunnel)
{
if (protocol != "http" && protocol != "https")
throw IllegalStateException("Protocol must be either http or https");

if (!connected())
{
_proxyConfig.host = host;
_proxyConfig.port = port;
_proxyConfig.protocol = protocol;
_proxyConfig.tunnel = tunnel;
}
else throw IllegalStateException("Cannot set the proxy host and port for an already connected session");
else throw IllegalStateException("Cannot set the proxy host, port and protocol for an already connected session");
}


Expand All @@ -159,6 +171,27 @@ void HTTPClientSession::setProxyPort(Poco::UInt16 port)
}


void HTTPClientSession::setProxyProtocol(const std::string& protocol)
{
if (protocol != "http" && protocol != "https")
throw IllegalStateException("Protocol must be either http or https");

if (!connected())
_proxyConfig.protocol = protocol;
else
throw IllegalStateException("Cannot set the proxy port number for an already connected session");
}


void HTTPClientSession::setProxyTunnel(bool tunnel)
{
if (!connected())
_proxyConfig.tunnel = tunnel;
else
throw IllegalStateException("Cannot set the proxy tunnel for an already connected session");
}


void HTTPClientSession::setProxyCredentials(const std::string& username, const std::string& password)
{
_proxyConfig.username = username;
Expand Down Expand Up @@ -522,23 +555,28 @@ void HTTPClientSession::sendChallengeRequest(const HTTPRequest& request, HTTPRes

StreamSocket HTTPClientSession::proxyConnect()
{
ProxyConfig emptyProxyConfig;
HTTPClientSession proxySession(getProxyHost(), getProxyPort(), emptyProxyConfig);
proxySession.setTimeout(getTimeout());
URI proxyUri;
proxyUri.setScheme(getProxyProtocol());
proxyUri.setHost(getProxyHost());
proxyUri.setPort(getProxyPort());

SharedPtr<HTTPClientSession> proxySession (HTTPSessionFactory::defaultFactory().createClientSession(proxyUri));

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(HTTPMessage::PROXY_CONNECTION, HTTPMessage::CONNECTION_KEEP_ALIVE);
proxyRequest.set(HTTPRequest::HOST, getHost());
proxySession.proxyAuthenticateImpl(proxyRequest, _proxyConfig);
proxySession.setKeepAlive(true);
proxySession.sendRequest(proxyRequest);
proxySession.receiveResponse(proxyResponse);
proxyRequest.set(HTTPRequest::HOST, targetAddress);
proxySession->proxyAuthenticateImpl(proxyRequest, _proxyConfig);
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();
return proxySession->detachSocket();
}


Expand Down
46 changes: 31 additions & 15 deletions NetSSL_OpenSSL/src/HTTPSClientSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@


#include "Poco/Net/HTTPSClientSession.h"
#include "Poco/Net/HTTPSSessionInstantiator.h"
#include "Poco/Net/SecureStreamSocket.h"
#include "Poco/Net/SecureStreamSocketImpl.h"
#include "Poco/Net/SSLManager.h"
Expand All @@ -36,6 +37,7 @@ HTTPSClientSession::HTTPSClientSession():
_pContext(SSLManager::instance().defaultClientContext())
{
setPort(HTTPS_PORT);
_proxySessionFactory.registerProtocol("https", new HTTPSSessionInstantiator);
}


Expand All @@ -44,6 +46,7 @@ HTTPSClientSession::HTTPSClientSession(const SecureStreamSocket& socket):
_pContext(socket.context())
{
setPort(HTTPS_PORT);
_proxySessionFactory.registerProtocol("https", new HTTPSSessionInstantiator);
}


Expand All @@ -53,6 +56,7 @@ HTTPSClientSession::HTTPSClientSession(const SecureStreamSocket& socket, Session
_pSession(pSession)
{
setPort(HTTPS_PORT);
_proxySessionFactory.registerProtocol("https", new HTTPSSessionInstantiator);
}


Expand All @@ -62,13 +66,15 @@ HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 por
{
setHost(host);
setPort(port);
_proxySessionFactory.registerProtocol("https", new HTTPSSessionInstantiator);
}


HTTPSClientSession::HTTPSClientSession(Context::Ptr pContext):
HTTPClientSession(SecureStreamSocket(pContext)),
_pContext(pContext)
{
_proxySessionFactory.registerProtocol("https", new HTTPSSessionInstantiator(pContext));
}


Expand All @@ -77,6 +83,7 @@ HTTPSClientSession::HTTPSClientSession(Context::Ptr pContext, Session::Ptr pSess
_pContext(pContext),
_pSession(pSession)
{
_proxySessionFactory.registerProtocol("https", new HTTPSSessionInstantiator(pContext));
}


Expand All @@ -86,6 +93,7 @@ HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 por
{
setHost(host);
setPort(port);
_proxySessionFactory.registerProtocol("https", new HTTPSSessionInstantiator(pContext));
}


Expand All @@ -96,11 +104,13 @@ HTTPSClientSession::HTTPSClientSession(const std::string& host, Poco::UInt16 por
{
setHost(host);
setPort(port);
_proxySessionFactory.registerProtocol("https", new HTTPSSessionInstantiator(pContext));
}


HTTPSClientSession::~HTTPSClientSession()
{
_proxySessionFactory.unregisterProtocol("https");
}


Expand All @@ -126,7 +136,11 @@ X509Certificate HTTPSClientSession::serverCertificate()

std::string HTTPSClientSession::proxyRequestPrefix() const
{
return std::string();
std::string result("https://");
result.append(getHost());
result.append(":");
NumberFormatter::append(result, getPort());
return result;
}


Expand All @@ -137,12 +151,24 @@ void HTTPSClientSession::proxyAuthenticate(HTTPRequest& request)

void HTTPSClientSession::connect(const SocketAddress& address)
{
if (getProxyHost().empty() || bypassProxy())
bool useProxy = !getProxyHost().empty() && !bypassProxy();

if (useProxy && isProxyTunnel())
{
StreamSocket proxySocket(proxyConnect());
SecureStreamSocket secureSocket = SecureStreamSocket::attach(proxySocket, getHost(), _pContext, _pSession);
attachSocket(secureSocket);
if (_pContext->sessionCacheEnabled())
{
_pSession = secureSocket.currentSession();
}
}
else
{
SecureStreamSocket sss(socket());
if (sss.getPeerHostName().empty())
if (sss.getPeerHostName().empty())
{
sss.setPeerHostName(getHost());
sss.setPeerHostName(useProxy ? getProxyHost() : getHost());
}
if (_pContext->sessionCacheEnabled())
{
Expand All @@ -154,16 +180,6 @@ void HTTPSClientSession::connect(const SocketAddress& address)
_pSession = sss.currentSession();
}
}
else
{
StreamSocket proxySocket(proxyConnect());
SecureStreamSocket secureSocket = SecureStreamSocket::attach(proxySocket, getHost(), _pContext, _pSession);
attachSocket(secureSocket);
if (_pContext->sessionCacheEnabled())
{
_pSession = secureSocket.currentSession();
}
}
}


Expand All @@ -172,7 +188,7 @@ int HTTPSClientSession::read(char* buffer, std::streamsize length)
try
{
return HTTPSession::read(buffer, length);
}
}
catch(SSLConnectionUnexpectedlyClosedException&)
{
return 0;
Expand Down