mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-01-31 18:07:14 +01:00
4a6bfc086c
Switched to POCO library for unified platform/library interface. Deprecated the external module API. It was creating more problems than solving. Removed most built-in libraries in favor of system libraries for easier maintenance. Cleaned and secured code with help from static analyzers.
424 lines
13 KiB
C++
424 lines
13 KiB
C++
//
|
|
// HTTPClientSession.h
|
|
//
|
|
// Library: Net
|
|
// Package: HTTPClient
|
|
// Module: HTTPClientSession
|
|
//
|
|
// Definition of the HTTPClientSession class.
|
|
//
|
|
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
|
|
// and Contributors.
|
|
//
|
|
// SPDX-License-Identifier: BSL-1.0
|
|
//
|
|
|
|
|
|
#ifndef Net_HTTPClientSession_INCLUDED
|
|
#define Net_HTTPClientSession_INCLUDED
|
|
|
|
|
|
#include "Poco/Net/Net.h"
|
|
#include "Poco/Net/HTTPSession.h"
|
|
#include "Poco/Net/HTTPBasicCredentials.h"
|
|
#include "Poco/Net/HTTPDigestCredentials.h"
|
|
#include "Poco/Net/HTTPNTLMCredentials.h"
|
|
#include "Poco/Net/SocketAddress.h"
|
|
#include "Poco/SharedPtr.h"
|
|
#include <istream>
|
|
#include <ostream>
|
|
|
|
|
|
namespace Poco {
|
|
namespace Net {
|
|
|
|
|
|
class HTTPRequest;
|
|
class HTTPResponse;
|
|
|
|
|
|
class Net_API HTTPClientSession: public HTTPSession
|
|
/// This class implements the client-side of
|
|
/// a HTTP session.
|
|
///
|
|
/// To send a HTTP request to a HTTP server, first
|
|
/// instantiate a HTTPClientSession object and
|
|
/// specify the server's host name and port number.
|
|
///
|
|
/// Then create a HTTPRequest object, fill it accordingly,
|
|
/// and pass it as argument to the sendRequest() method.
|
|
///
|
|
/// sendRequest() will return an output stream that can
|
|
/// be used to send the request body, if there is any.
|
|
///
|
|
/// After you are done sending the request body, create
|
|
/// a HTTPResponse object and pass it to receiveResponse().
|
|
///
|
|
/// This will return an input stream that can be used to
|
|
/// read the response body.
|
|
///
|
|
/// See RFC 2616 <http://www.faqs.org/rfcs/rfc2616.html> for more
|
|
/// information about the HTTP protocol.
|
|
///
|
|
/// Proxies and proxy authorization (only HTTP Basic Authorization)
|
|
/// is supported. Use setProxy() and setProxyCredentials() to
|
|
/// set up a session through a proxy.
|
|
{
|
|
public:
|
|
enum ProxyAuthentication
|
|
{
|
|
PROXY_AUTH_NONE, /// No proxy authentication
|
|
PROXY_AUTH_HTTP_BASIC, /// HTTP Basic proxy authentication (default, if username and password are supplied)
|
|
PROXY_AUTH_HTTP_DIGEST, /// HTTP Digest proxy authentication
|
|
PROXY_AUTH_NTLM /// NTLMv2 proxy authentication
|
|
};
|
|
|
|
struct ProxyConfig
|
|
/// HTTP proxy server configuration.
|
|
{
|
|
ProxyConfig():
|
|
port(HTTP_PORT),
|
|
authMethod(PROXY_AUTH_HTTP_BASIC)
|
|
{
|
|
}
|
|
|
|
std::string host;
|
|
/// Proxy server host name or IP address.
|
|
Poco::UInt16 port;
|
|
/// Proxy server TCP port.
|
|
std::string username;
|
|
/// Proxy server username.
|
|
std::string password;
|
|
/// Proxy server password.
|
|
std::string nonProxyHosts;
|
|
/// A regular expression defining hosts for which the proxy should be bypassed,
|
|
/// e.g. "localhost|127\.0\.0\.1|192\.168\.0\.\d+". Can also be an empty
|
|
/// string to disable proxy bypassing.
|
|
|
|
ProxyAuthentication authMethod;
|
|
/// The authentication method to use - HTTP Basic or NTLM.
|
|
};
|
|
|
|
HTTPClientSession();
|
|
/// Creates an unconnected HTTPClientSession.
|
|
|
|
explicit HTTPClientSession(const StreamSocket& socket);
|
|
/// Creates a HTTPClientSession using the given socket.
|
|
/// The socket must not be connected. The session
|
|
/// takes ownership of the socket.
|
|
|
|
explicit HTTPClientSession(const SocketAddress& address);
|
|
/// Creates a HTTPClientSession using the given address.
|
|
|
|
HTTPClientSession(const std::string& host, Poco::UInt16 port = HTTPSession::HTTP_PORT);
|
|
/// Creates a HTTPClientSession using the given host and port.
|
|
|
|
HTTPClientSession(const std::string& host, Poco::UInt16 port, const ProxyConfig& proxyConfig);
|
|
/// Creates a HTTPClientSession using the given host, port and proxy configuration.
|
|
|
|
virtual ~HTTPClientSession();
|
|
/// Destroys the HTTPClientSession and closes
|
|
/// the underlying socket.
|
|
|
|
void setHost(const std::string& host);
|
|
/// Sets the host name of the target HTTP server.
|
|
///
|
|
/// The host must not be changed once there is an
|
|
/// open connection to the server.
|
|
|
|
const std::string& getHost() const;
|
|
/// Returns the host name of the target HTTP server.
|
|
|
|
void setPort(Poco::UInt16 port);
|
|
/// Sets the port number of the target HTTP server.
|
|
///
|
|
/// The port number must not be changed once there is an
|
|
/// open connection to the server.
|
|
|
|
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 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.
|
|
|
|
const std::string& getProxyHost() const;
|
|
/// Returns the proxy host name.
|
|
|
|
Poco::UInt16 getProxyPort() const;
|
|
/// Returns the proxy port number.
|
|
|
|
void setProxyCredentials(const std::string& username, const std::string& password);
|
|
/// Sets the username and password for proxy authentication.
|
|
/// Only Basic authentication is supported.
|
|
|
|
void setProxyUsername(const std::string& username);
|
|
/// Sets the username for proxy authentication.
|
|
/// Only Basic authentication is supported.
|
|
|
|
const std::string& getProxyUsername() const;
|
|
/// Returns the username for proxy authentication.
|
|
|
|
void setProxyPassword(const std::string& password);
|
|
/// Sets the password for proxy authentication.
|
|
/// Only Basic authentication is supported.
|
|
|
|
const std::string& getProxyPassword() const;
|
|
/// Returns the password for proxy authentication.
|
|
|
|
void setProxyConfig(const ProxyConfig& config);
|
|
/// Sets the proxy configuration.
|
|
|
|
const ProxyConfig& getProxyConfig() const;
|
|
/// Returns the proxy configuration.
|
|
|
|
static void setGlobalProxyConfig(const ProxyConfig& config);
|
|
/// Sets the global proxy configuration.
|
|
///
|
|
/// The global proxy configuration is used by all HTTPClientSession
|
|
/// instances, unless a different proxy configuration is explicitly set.
|
|
///
|
|
/// Warning: Setting the global proxy configuration is not thread safe.
|
|
/// The global proxy configuration should be set at start up, before
|
|
/// the first HTTPClientSession instance is created.
|
|
|
|
static const ProxyConfig& getGlobalProxyConfig();
|
|
/// Returns the global proxy configuration.
|
|
|
|
void setKeepAliveTimeout(const Poco::Timespan& timeout);
|
|
/// Sets the connection timeout for HTTP connections.
|
|
|
|
const Poco::Timespan& getKeepAliveTimeout() const;
|
|
/// Returns the connection timeout for HTTP connections.
|
|
|
|
virtual std::ostream& sendRequest(HTTPRequest& request);
|
|
/// Sends the header for the given HTTP request to
|
|
/// the server.
|
|
///
|
|
/// The HTTPClientSession will set the request's
|
|
/// Host and Keep-Alive headers accordingly.
|
|
///
|
|
/// The returned output stream can be used to write
|
|
/// the request body. The stream is valid until
|
|
/// receiveResponse() is called or the session
|
|
/// is destroyed.
|
|
///
|
|
/// In case a network or server failure happens
|
|
/// while writing the request body to the returned stream,
|
|
/// the stream state will change to bad or fail. In this
|
|
/// case, reset() should be called if the session will
|
|
/// be reused and persistent connections are enabled
|
|
/// to ensure a new connection will be set up
|
|
/// for the next request.
|
|
|
|
virtual std::istream& receiveResponse(HTTPResponse& response);
|
|
/// Receives the header for the response to the previous
|
|
/// HTTP request.
|
|
///
|
|
/// The returned input stream can be used to read
|
|
/// the response body. The stream is valid until
|
|
/// sendRequest() is called or the session is
|
|
/// destroyed.
|
|
///
|
|
/// It must be ensured that the response stream
|
|
/// is fully consumed before sending a new request
|
|
/// and persistent connections are enabled. Otherwise,
|
|
/// the unread part of the response body may be treated as
|
|
/// part of the next request's response header, resulting
|
|
/// in a Poco::Net::MessageException being thrown.
|
|
///
|
|
/// In case a network or server failure happens
|
|
/// while reading the response body from the returned stream,
|
|
/// the stream state will change to bad or fail. In this
|
|
/// case, reset() should be called if the session will
|
|
/// be reused and persistent connections are enabled
|
|
/// to ensure a new connection will be set up
|
|
/// for the next request.
|
|
|
|
virtual bool peekResponse(HTTPResponse& response);
|
|
/// If the request contains a "Expect: 100-continue" header,
|
|
/// (see HTTPRequest::setExpectContinue()) this method can be
|
|
/// used to check whether the server has sent a 100 Continue response
|
|
/// before continuing with the request, i.e. sending the request body,
|
|
/// after calling sendRequest().
|
|
///
|
|
/// Returns true if the server has responded with 100 Continue,
|
|
/// otherwise false. The HTTPResponse object contains the
|
|
/// response sent by the server.
|
|
///
|
|
/// In any case, receiveResponse() must be called afterwards as well in
|
|
/// order to complete the request. The same HTTPResponse object
|
|
/// passed to peekResponse() must also be passed to receiveResponse().
|
|
///
|
|
/// This method should only be called if the request contains
|
|
/// a "Expect: 100-continue" header.
|
|
|
|
void flushRequest();
|
|
/// Flushes the request stream.
|
|
///
|
|
/// Normally this method does not need to be called.
|
|
/// It can be used to ensure the request has been
|
|
/// fully sent if receiveResponse() is not called, e.g.,
|
|
/// because the underlying socket will be detached.
|
|
|
|
void reset();
|
|
/// Resets the session and closes the socket.
|
|
///
|
|
/// The next request will initiate a new connection,
|
|
/// even if persistent connections are enabled.
|
|
///
|
|
/// This should be called whenever something went
|
|
/// wrong when sending a request (e.g., sendRequest()
|
|
/// or receiveResponse() throws an exception, or
|
|
/// the request or response stream changes into
|
|
/// fail or bad state, but not eof state).
|
|
|
|
virtual bool secure() const;
|
|
/// Return true iff the session uses SSL or TLS,
|
|
/// or false otherwise.
|
|
|
|
bool bypassProxy() const;
|
|
/// Returns true if the proxy should be bypassed
|
|
/// for the current host.
|
|
|
|
protected:
|
|
enum
|
|
{
|
|
DEFAULT_KEEP_ALIVE_TIMEOUT = 8
|
|
};
|
|
|
|
void reconnect();
|
|
/// Connects the underlying socket to the HTTP server.
|
|
|
|
int write(const char* buffer, std::streamsize length);
|
|
/// Tries to re-connect if keep-alive is on.
|
|
|
|
std::ostream& sendRequestImpl(const HTTPRequest& request);
|
|
/// Sends the given HTTPRequest over an existing connection.
|
|
|
|
virtual std::string proxyRequestPrefix() const;
|
|
/// Returns the prefix prepended to the URI for proxy requests
|
|
/// (e.g., "http://myhost.com").
|
|
|
|
virtual bool mustReconnect() const;
|
|
/// Checks if we can reuse a persistent connection.
|
|
|
|
virtual void proxyAuthenticate(HTTPRequest& request);
|
|
/// Sets the proxy credentials (Proxy-Authorization header), if
|
|
/// proxy username and password have been set.
|
|
|
|
void proxyAuthenticateImpl(HTTPRequest& request, const ProxyConfig& proxyConfig);
|
|
/// Sets the proxy credentials (Proxy-Authorization header), if
|
|
/// proxy username and password have been set.
|
|
|
|
void proxyAuthenticateDigest(HTTPRequest& request);
|
|
/// Initiates a HTTP Digest authentication handshake with the proxy.
|
|
|
|
void proxyAuthenticateNTLM(HTTPRequest& request);
|
|
/// Initiates a HTTP NTLM authentication handshake with the proxy.
|
|
|
|
void sendChallengeRequest(const HTTPRequest& request, HTTPResponse& response);
|
|
/// Sends a probe request for Digest and NTLM authentication
|
|
/// to obtain the server challenge.
|
|
|
|
StreamSocket proxyConnect();
|
|
/// Sends a CONNECT request to the proxy server and returns
|
|
/// a StreamSocket for the resulting connection.
|
|
|
|
void proxyTunnel();
|
|
/// Calls proxyConnect() and attaches the resulting StreamSocket
|
|
/// to the HTTPClientSession.
|
|
|
|
private:
|
|
std::string _host;
|
|
Poco::UInt16 _port;
|
|
ProxyConfig _proxyConfig;
|
|
Poco::Timespan _keepAliveTimeout;
|
|
Poco::Timestamp _lastRequest;
|
|
bool _reconnect;
|
|
bool _mustReconnect;
|
|
bool _expectResponseBody;
|
|
bool _responseReceived;
|
|
Poco::SharedPtr<std::ostream> _pRequestStream;
|
|
Poco::SharedPtr<std::istream> _pResponseStream;
|
|
HTTPBasicCredentials _proxyBasicCreds;
|
|
HTTPDigestCredentials _proxyDigestCreds;
|
|
HTTPNTLMCredentials _proxyNTLMCreds;
|
|
bool _ntlmProxyAuthenticated;
|
|
|
|
static ProxyConfig _globalProxyConfig;
|
|
|
|
HTTPClientSession(const HTTPClientSession&);
|
|
HTTPClientSession& operator = (const HTTPClientSession&);
|
|
|
|
friend class WebSocket;
|
|
};
|
|
|
|
|
|
//
|
|
// inlines
|
|
//
|
|
inline const std::string& HTTPClientSession::getHost() const
|
|
{
|
|
return _host;
|
|
}
|
|
|
|
|
|
inline Poco::UInt16 HTTPClientSession::getPort() const
|
|
{
|
|
return _port;
|
|
}
|
|
|
|
|
|
inline const std::string& HTTPClientSession::getProxyHost() const
|
|
{
|
|
return _proxyConfig.host;
|
|
}
|
|
|
|
|
|
inline Poco::UInt16 HTTPClientSession::getProxyPort() const
|
|
{
|
|
return _proxyConfig.port;
|
|
}
|
|
|
|
|
|
inline const std::string& HTTPClientSession::getProxyUsername() const
|
|
{
|
|
return _proxyConfig.username;
|
|
}
|
|
|
|
|
|
inline const std::string& HTTPClientSession::getProxyPassword() const
|
|
{
|
|
return _proxyConfig.password;
|
|
}
|
|
|
|
|
|
inline const HTTPClientSession::ProxyConfig& HTTPClientSession::getProxyConfig() const
|
|
{
|
|
return _proxyConfig;
|
|
}
|
|
|
|
|
|
inline const HTTPClientSession::ProxyConfig& HTTPClientSession::getGlobalProxyConfig()
|
|
{
|
|
return _globalProxyConfig;
|
|
}
|
|
|
|
|
|
inline const Poco::Timespan& HTTPClientSession::getKeepAliveTimeout() const
|
|
{
|
|
return _keepAliveTimeout;
|
|
}
|
|
|
|
|
|
} } // namespace Poco::Net
|
|
|
|
|
|
#endif // Net_HTTPClientSession_INCLUDED
|