Skip to content

Commit 420c3b5

Browse files
committed
added support for global HTTP proxy configuration
1 parent 9dfffed commit 420c3b5

4 files changed

Lines changed: 117 additions & 33 deletions

File tree

‎Net/include/Poco/Net/HTTPClientSession.h‎

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,20 @@ class Net_API HTTPClientSession: public HTTPSession
6464
/// set up a session through a proxy.
6565
{
6666
public:
67+
struct ProxyConfig
68+
/// HTTP proxy server configuration.
69+
{
70+
ProxyConfig():
71+
port(HTTP_PORT)
72+
{
73+
}
74+
75+
std::string host; /// Proxy server host name or IP address.
76+
Poco::UInt16 port; /// Proxy server TCP port.
77+
std::string username; /// Proxy server username.
78+
std::string password; /// Proxy server password.
79+
};
80+
6781
HTTPClientSession();
6882
/// Creates an unconnected HTTPClientSession.
6983

@@ -133,6 +147,25 @@ class Net_API HTTPClientSession: public HTTPSession
133147
const std::string& getProxyPassword() const;
134148
/// Returns the password for proxy authentication.
135149

150+
void setProxyConfig(const ProxyConfig& config);
151+
/// Sets the proxy configuration.
152+
153+
const ProxyConfig& getProxyConfig() const;
154+
/// Returns the proxy configuration.
155+
156+
static void setGlobalProxyConfig(const ProxyConfig& config);
157+
/// Sets the global proxy configuration.
158+
///
159+
/// The global proxy configuration is used by all HTTPClientSession
160+
/// instances, unless a different proxy configuration is explicitly set.
161+
///
162+
/// Warning: Setting the global proxy configuration is not thread safe.
163+
/// The global proxy configuration should be set at start up, before
164+
/// the first HTTPClientSession instance is created.
165+
166+
static const ProxyConfig& getGlobalProxyConfig();
167+
/// Returns the global proxy configuration.
168+
136169
void setKeepAliveTimeout(const Poco::Timespan& timeout);
137170
/// Sets the connection timeout for HTTP connections.
138171

@@ -198,7 +231,7 @@ class Net_API HTTPClientSession: public HTTPSession
198231
virtual bool secure() const;
199232
/// Return true iff the session uses SSL or TLS,
200233
/// or false otherwise.
201-
234+
202235
protected:
203236
enum
204237
{
@@ -237,17 +270,16 @@ class Net_API HTTPClientSession: public HTTPSession
237270
private:
238271
std::string _host;
239272
Poco::UInt16 _port;
240-
std::string _proxyHost;
241-
Poco::UInt16 _proxyPort;
242-
std::string _proxyUsername;
243-
std::string _proxyPassword;
273+
ProxyConfig _proxyConfig;
244274
Poco::Timespan _keepAliveTimeout;
245275
Poco::Timestamp _lastRequest;
246276
bool _reconnect;
247277
bool _mustReconnect;
248278
bool _expectResponseBody;
249279
Poco::SharedPtr<std::ostream> _pRequestStream;
250280
Poco::SharedPtr<std::istream> _pResponseStream;
281+
282+
static ProxyConfig _globalProxyConfig;
251283

252284
HTTPClientSession(const HTTPClientSession&);
253285
HTTPClientSession& operator = (const HTTPClientSession&);
@@ -273,25 +305,37 @@ inline Poco::UInt16 HTTPClientSession::getPort() const
273305

274306
inline const std::string& HTTPClientSession::getProxyHost() const
275307
{
276-
return _proxyHost;
308+
return _proxyConfig.host;
277309
}
278310

279311

280312
inline Poco::UInt16 HTTPClientSession::getProxyPort() const
281313
{
282-
return _proxyPort;
314+
return _proxyConfig.port;
283315
}
284316

285317

286318
inline const std::string& HTTPClientSession::getProxyUsername() const
287319
{
288-
return _proxyUsername;
320+
return _proxyConfig.username;
289321
}
290322

291323

292324
inline const std::string& HTTPClientSession::getProxyPassword() const
293325
{
294-
return _proxyPassword;
326+
return _proxyConfig.password;
327+
}
328+
329+
330+
inline const HTTPClientSession::ProxyConfig& HTTPClientSession::getProxyConfig() const
331+
{
332+
return _proxyConfig;
333+
}
334+
335+
336+
inline const HTTPClientSession::ProxyConfig& HTTPClientSession::getGlobalProxyConfig()
337+
{
338+
return _globalProxyConfig;
295339
}
296340

297341

‎Net/src/HTTPClientSession.cpp‎

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,12 @@ namespace Poco {
3737
namespace Net {
3838

3939

40+
HTTPClientSession::ProxyConfig HTTPClientSession::_globalProxyConfig;
41+
42+
4043
HTTPClientSession::HTTPClientSession():
4144
_port(HTTPSession::HTTP_PORT),
42-
_proxyPort(HTTPSession::HTTP_PORT),
45+
_proxyConfig(_globalProxyConfig),
4346
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
4447
_reconnect(false),
4548
_mustReconnect(false),
@@ -51,7 +54,7 @@ HTTPClientSession::HTTPClientSession():
5154
HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
5255
HTTPSession(socket),
5356
_port(HTTPSession::HTTP_PORT),
54-
_proxyPort(HTTPSession::HTTP_PORT),
57+
_proxyConfig(_globalProxyConfig),
5558
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
5659
_reconnect(false),
5760
_mustReconnect(false),
@@ -63,7 +66,7 @@ HTTPClientSession::HTTPClientSession(const StreamSocket& socket):
6366
HTTPClientSession::HTTPClientSession(const SocketAddress& address):
6467
_host(address.host().toString()),
6568
_port(address.port()),
66-
_proxyPort(HTTPSession::HTTP_PORT),
69+
_proxyConfig(_globalProxyConfig),
6770
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
6871
_reconnect(false),
6972
_mustReconnect(false),
@@ -75,7 +78,7 @@ HTTPClientSession::HTTPClientSession(const SocketAddress& address):
7578
HTTPClientSession::HTTPClientSession(const std::string& host, Poco::UInt16 port):
7679
_host(host),
7780
_port(port),
78-
_proxyPort(HTTPSession::HTTP_PORT),
81+
_proxyConfig(_globalProxyConfig),
7982
_keepAliveTimeout(DEFAULT_KEEP_ALIVE_TIMEOUT, 0),
8083
_reconnect(false),
8184
_mustReconnect(false),
@@ -111,8 +114,8 @@ void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port)
111114
{
112115
if (!connected())
113116
{
114-
_proxyHost = host;
115-
_proxyPort = port;
117+
_proxyConfig.host = host;
118+
_proxyConfig.port = port;
116119
}
117120
else throw IllegalStateException("Cannot set the proxy host and port for an already connected session");
118121
}
@@ -121,7 +124,7 @@ void HTTPClientSession::setProxy(const std::string& host, Poco::UInt16 port)
121124
void HTTPClientSession::setProxyHost(const std::string& host)
122125
{
123126
if (!connected())
124-
_proxyHost = host;
127+
_proxyConfig.host = host;
125128
else
126129
throw IllegalStateException("Cannot set the proxy host for an already connected session");
127130
}
@@ -130,31 +133,43 @@ void HTTPClientSession::setProxyHost(const std::string& host)
130133
void HTTPClientSession::setProxyPort(Poco::UInt16 port)
131134
{
132135
if (!connected())
133-
_proxyPort = port;
136+
_proxyConfig.port = port;
134137
else
135138
throw IllegalStateException("Cannot set the proxy port number for an already connected session");
136139
}
137140

138141

139142
void HTTPClientSession::setProxyCredentials(const std::string& username, const std::string& password)
140143
{
141-
_proxyUsername = username;
142-
_proxyPassword = password;
144+
_proxyConfig.username = username;
145+
_proxyConfig.password = password;
143146
}
144147

145148

146149
void HTTPClientSession::setProxyUsername(const std::string& username)
147150
{
148-
_proxyUsername = username;
151+
_proxyConfig.username = username;
149152
}
150153

151154

152155
void HTTPClientSession::setProxyPassword(const std::string& password)
153156
{
154-
_proxyPassword = password;
157+
_proxyConfig.password = password;
155158
}
156159

157-
160+
161+
void HTTPClientSession::setProxyConfig(const ProxyConfig& config)
162+
{
163+
_proxyConfig = config;
164+
}
165+
166+
167+
void HTTPClientSession::setGlobalProxyConfig(const ProxyConfig& config)
168+
{
169+
_globalProxyConfig = config;
170+
}
171+
172+
158173
void HTTPClientSession::setKeepAliveTimeout(const Poco::Timespan& timeout)
159174
{
160175
_keepAliveTimeout = timeout;
@@ -180,7 +195,7 @@ std::ostream& HTTPClientSession::sendRequest(HTTPRequest& request)
180195
request.setKeepAlive(false);
181196
if (!request.has(HTTPRequest::HOST))
182197
request.setHost(_host, _port);
183-
if (!_proxyHost.empty())
198+
if (!_proxyConfig.host.empty())
184199
{
185200
request.setURI(proxyRequestPrefix() + request.getURI());
186201
proxyAuthenticate(request);
@@ -312,14 +327,14 @@ int HTTPClientSession::write(const char* buffer, std::streamsize length)
312327

313328
void HTTPClientSession::reconnect()
314329
{
315-
if (_proxyHost.empty())
330+
if (_proxyConfig.host.empty())
316331
{
317332
SocketAddress addr(_host, _port);
318333
connect(addr);
319334
}
320335
else
321336
{
322-
SocketAddress addr(_proxyHost, _proxyPort);
337+
SocketAddress addr(_proxyConfig.host, _proxyConfig.port);
323338
connect(addr);
324339
}
325340
}
@@ -354,9 +369,9 @@ void HTTPClientSession::proxyAuthenticate(HTTPRequest& request)
354369

355370
void HTTPClientSession::proxyAuthenticateImpl(HTTPRequest& request)
356371
{
357-
if (!_proxyUsername.empty())
372+
if (!_proxyConfig.username.empty())
358373
{
359-
HTTPBasicCredentials creds(_proxyUsername, _proxyPassword);
374+
HTTPBasicCredentials creds(_proxyConfig.username, _proxyConfig.password);
360375
creds.proxyAuthenticate(request);
361376
}
362377
}

‎Net/src/HTTPStreamFactory.cpp‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,21 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
8787
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
8888

8989
if (proxyUri.empty())
90-
pSession->setProxy(_proxyHost, _proxyPort);
90+
{
91+
if (!_proxyHost.empty())
92+
{
93+
pSession->setProxy(_proxyHost, _proxyPort);
94+
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
95+
}
96+
}
9197
else
98+
{
9299
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
93-
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
100+
if (!_proxyUsername.empty())
101+
{
102+
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
103+
}
104+
}
94105
}
95106

96107
std::string path = resolvedURI.getPathAndQuery();
@@ -131,7 +142,8 @@ std::istream* HTTPStreamFactory::open(const URI& uri)
131142
// single request via the proxy. 305 responses MUST only be generated by origin servers.
132143
// only use for one single request!
133144
proxyUri.resolve(res.get("Location"));
134-
delete pSession; pSession = 0;
145+
delete pSession;
146+
pSession = 0;
135147
retry = true; // only allow useproxy once
136148
}
137149
else if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize)

‎NetSSL_OpenSSL/src/HTTPSStreamFactory.cpp‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,23 @@ std::istream* HTTPSStreamFactory::open(const URI& uri)
8989
pSession = new HTTPSClientSession(resolvedURI.getHost(), resolvedURI.getPort());
9090
else
9191
pSession = new HTTPClientSession(resolvedURI.getHost(), resolvedURI.getPort());
92+
9293
if (proxyUri.empty())
93-
pSession->setProxy(_proxyHost, _proxyPort);
94+
{
95+
if (!_proxyHost.empty())
96+
{
97+
pSession->setProxy(_proxyHost, _proxyPort);
98+
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
99+
}
100+
}
94101
else
102+
{
95103
pSession->setProxy(proxyUri.getHost(), proxyUri.getPort());
96-
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
104+
if (!_proxyUsername.empty())
105+
{
106+
pSession->setProxyCredentials(_proxyUsername, _proxyPassword);
107+
}
108+
}
97109
}
98110
std::string path = resolvedURI.getPathAndQuery();
99111
if (path.empty()) path = "/";
@@ -136,7 +148,8 @@ std::istream* HTTPSStreamFactory::open(const URI& uri)
136148
// single request via the proxy. 305 responses MUST only be generated by origin servers.
137149
// only use for one single request!
138150
proxyUri.resolve(res.get("Location"));
139-
delete pSession; pSession = 0;
151+
delete pSession;
152+
pSession = 0;
140153
retry = true; // only allow useproxy once
141154
}
142155
else if (res.getStatus() == HTTPResponse::HTTP_UNAUTHORIZED && !authorize)

0 commit comments

Comments
 (0)