From 80447a4edbeca38f5ca8477e3f10757b7e091dfe Mon Sep 17 00:00:00 2001 From: cantor Date: Thu, 15 Feb 2007 22:44:59 +0000 Subject: [PATCH] Correct constness of transport API, handle both chunked and buffered encoding. git-svn-id: https://svn.middleware.georgetown.edu/cpp-xmltooling/trunk@260 de75baf8-a10c-0410-a50a-987c0e22f00f --- xmltooling/soap/HTTPSOAPTransport.h | 11 ++++- xmltooling/soap/OpenSSLSOAPTransport.h | 2 +- xmltooling/soap/SOAPClient.h | 2 +- xmltooling/soap/SOAPTransport.h | 10 ++--- xmltooling/soap/impl/CURLSOAPTransport.cpp | 64 ++++++++++++++++++++---------- 5 files changed, 59 insertions(+), 30 deletions(-) diff --git a/xmltooling/soap/HTTPSOAPTransport.h b/xmltooling/soap/HTTPSOAPTransport.h index 2a24253..3623f04 100644 --- a/xmltooling/soap/HTTPSOAPTransport.h +++ b/xmltooling/soap/HTTPSOAPTransport.h @@ -40,13 +40,22 @@ namespace xmltooling { virtual ~HTTPSOAPTransport() {} /** + * Indicate whether content should be sent using HTTP 1.1 and + * Chunked Transport-Encoding, or buffered and sent with a Content-Length. + * + * @param chunked true iff chunked encoding should be used + * @return true iff the property is successfully set + */ + virtual bool useChunkedEncoding(bool chunked=true)=0; + + /** * Sets an outgoing HTTP request header. * * @param name name of header, without the colon separator * @param value header value to send * @return true iff the header is successfully set */ - virtual bool setRequestHeader(const char* name, const char* value) const=0; + virtual bool setRequestHeader(const char* name, const char* value)=0; /** * Returns the values of an HTTP response header. diff --git a/xmltooling/soap/OpenSSLSOAPTransport.h b/xmltooling/soap/OpenSSLSOAPTransport.h index 2545e78..6cd0369 100644 --- a/xmltooling/soap/OpenSSLSOAPTransport.h +++ b/xmltooling/soap/OpenSSLSOAPTransport.h @@ -49,7 +49,7 @@ namespace xmltooling { * @param userptr a caller-supplied value to pass to the callback function * @return true iff the callback was set */ - virtual bool setSSLCallback(ssl_ctx_callback_fn fn, void* userptr=NULL) const=0; + virtual bool setSSLCallback(ssl_ctx_callback_fn fn, void* userptr=NULL)=0; /** * Sets indicator that the transport peer has been authenticated. diff --git a/xmltooling/soap/SOAPClient.h b/xmltooling/soap/SOAPClient.h index aff5edf..ee33004 100644 --- a/xmltooling/soap/SOAPClient.h +++ b/xmltooling/soap/SOAPClient.h @@ -94,7 +94,7 @@ namespace soap11 { * * @param transport reference to transport layer */ - virtual void prepareTransport(const xmltooling::SOAPTransport& transport) {} + virtual void prepareTransport(xmltooling::SOAPTransport& transport) {} /** * Handling of SOAP faults. diff --git a/xmltooling/soap/SOAPTransport.h b/xmltooling/soap/SOAPTransport.h index 6cf547d..cdebd4b 100644 --- a/xmltooling/soap/SOAPTransport.h +++ b/xmltooling/soap/SOAPTransport.h @@ -62,7 +62,7 @@ namespace xmltooling { * @param timeout time to wait for connection to server in seconds, or -1 for no timeout * @return true iff the transport supports connection timeouts */ - virtual bool setConnectTimeout(long timeout) const=0; + virtual bool setConnectTimeout(long timeout)=0; /** * Sets the request timeout. @@ -70,7 +70,7 @@ namespace xmltooling { * @param timeout time to wait for a response in seconds, or -1 for no timeout * @return true iff the transport supports request/response timeouts */ - virtual bool setTimeout(long timeout) const=0; + virtual bool setTimeout(long timeout)=0; /** * Common types of transport authentication that may be supported. @@ -91,7 +91,7 @@ namespace xmltooling { * @param password simple password/credential for transport authentication * @return true iff the transport supports the indicated form of authentication */ - virtual bool setAuth(transport_auth_t authType, const char* username=NULL, const char* password=NULL) const=0; + virtual bool setAuth(transport_auth_t authType, const char* username=NULL, const char* password=NULL)=0; #ifndef XMLTOOLING_NO_XMLSEC /** @@ -103,7 +103,7 @@ namespace xmltooling { * @param credResolver a locked CredentialResolver instance, or NULL * @return true iff the transport supports the use of a CredentialResolver */ - virtual bool setCredentialResolver(const xmlsignature::CredentialResolver* credResolver) const=0; + virtual bool setCredentialResolver(const xmlsignature::CredentialResolver* credResolver)=0; /** * Provides a TrustEngine to the transport to authenticate the transport peer. @@ -119,7 +119,7 @@ namespace xmltooling { const X509TrustEngine* trustEngine, bool mandatory=true, const xmlsignature::KeyResolver* keyResolver=NULL - ) const=0; + )=0; #endif /** diff --git a/xmltooling/soap/impl/CURLSOAPTransport.cpp b/xmltooling/soap/impl/CURLSOAPTransport.cpp index a5e49bb..34359b4 100644 --- a/xmltooling/soap/impl/CURLSOAPTransport.cpp +++ b/xmltooling/soap/impl/CURLSOAPTransport.cpp @@ -71,7 +71,7 @@ namespace xmltooling { #ifndef XMLTOOLING_NO_XMLSEC m_credResolver(NULL), m_trustEngine(NULL), m_mandatory(false), m_keyResolver(NULL), #endif - m_ssl_callback(NULL), m_ssl_userptr(NULL), m_secure(false) { + m_ssl_callback(NULL), m_ssl_userptr(NULL), m_chunked(true), m_secure(false) { m_handle = g_CURLPool->get(peer.getName(), endpoint); curl_easy_setopt(m_handle,CURLOPT_URL,endpoint); curl_easy_setopt(m_handle,CURLOPT_CONNECTTIMEOUT,15); @@ -80,7 +80,6 @@ namespace xmltooling { curl_easy_setopt(m_handle,CURLOPT_USERPWD,NULL); curl_easy_setopt(m_handle,CURLOPT_HEADERDATA,this); m_headers=curl_slist_append(m_headers,"Content-Type: text/xml"); - m_headers=curl_slist_append(m_headers,"Transport-Encoding: chunked"); } virtual ~CURLSOAPTransport() { @@ -94,18 +93,18 @@ namespace xmltooling { return m_endpoint.find("https")==0; } - bool setConnectTimeout(long timeout) const { + bool setConnectTimeout(long timeout) { return (curl_easy_setopt(m_handle,CURLOPT_CONNECTTIMEOUT,timeout)==CURLE_OK); } - bool setTimeout(long timeout) const { + bool setTimeout(long timeout) { return (curl_easy_setopt(m_handle,CURLOPT_TIMEOUT,timeout)==CURLE_OK); } - bool setAuth(transport_auth_t authType, const char* username=NULL, const char* password=NULL) const; + bool setAuth(transport_auth_t authType, const char* username=NULL, const char* password=NULL); #ifndef XMLTOOLING_NO_XMLSEC - bool setCredentialResolver(const CredentialResolver* credResolver) const { + bool setCredentialResolver(const CredentialResolver* credResolver) { const OpenSSLCredentialResolver* down = dynamic_cast(credResolver); if (!down) { m_credResolver = NULL; @@ -115,7 +114,7 @@ namespace xmltooling { return true; } - bool setTrustEngine(const X509TrustEngine* trustEngine, bool mandatory=true, const KeyResolver* keyResolver=NULL) const { + bool setTrustEngine(const X509TrustEngine* trustEngine, bool mandatory=true, const KeyResolver* keyResolver=NULL) { const OpenSSLTrustEngine* down = dynamic_cast(trustEngine); if (!down) { m_trustEngine = NULL; @@ -130,6 +129,11 @@ namespace xmltooling { #endif + bool useChunkedEncoding(bool chunked=true) { + m_chunked = chunked; + return true; + } + void send(istream& in); istream& receive() { @@ -146,7 +150,7 @@ namespace xmltooling { string getContentType() const; - bool setRequestHeader(const char* name, const char* val) const { + bool setRequestHeader(const char* name, const char* val) { string temp(name); temp=temp + ": " + val; m_headers=curl_slist_append(m_headers,temp.c_str()); @@ -155,7 +159,7 @@ namespace xmltooling { const vector& getResponseHeader(const char* val) const; - bool setSSLCallback(ssl_ctx_callback_fn fn, void* userptr=NULL) const { + bool setSSLCallback(ssl_ctx_callback_fn fn, void* userptr=NULL) { m_ssl_callback=fn; m_ssl_userptr=userptr; return true; @@ -167,16 +171,17 @@ namespace xmltooling { string m_endpoint; CURL* m_handle; stringstream m_stream; - mutable struct curl_slist* m_headers; + struct curl_slist* m_headers; map > m_response_headers; #ifndef XMLTOOLING_NO_XMLSEC - mutable const OpenSSLCredentialResolver* m_credResolver; - mutable const OpenSSLTrustEngine* m_trustEngine; - mutable bool m_mandatory; - mutable const KeyResolver* m_keyResolver; + const OpenSSLCredentialResolver* m_credResolver; + const OpenSSLTrustEngine* m_trustEngine; + bool m_mandatory; + const KeyResolver* m_keyResolver; #endif - mutable ssl_ctx_callback_fn m_ssl_callback; - mutable void* m_ssl_userptr; + ssl_ctx_callback_fn m_ssl_callback; + void* m_ssl_userptr; + bool m_chunked; bool m_secure; friend size_t XMLTOOL_DLLLOCAL curl_header_hook(void* ptr, size_t size, size_t nmemb, void* stream); @@ -267,7 +272,6 @@ CURL* CURLPool::get(const string& to, const char* endpoint) curl_easy_setopt(handle,CURLOPT_SSL_VERIFYPEER,0); curl_easy_setopt(handle,CURLOPT_SSL_VERIFYHOST,2); curl_easy_setopt(handle,CURLOPT_HEADERFUNCTION,&curl_header_hook); - curl_easy_setopt(handle,CURLOPT_READFUNCTION,&curl_read_hook); curl_easy_setopt(handle,CURLOPT_WRITEFUNCTION,&curl_write_hook); curl_easy_setopt(handle,CURLOPT_DEBUGFUNCTION,&curl_debug_hook); @@ -311,7 +315,7 @@ void CURLPool::put(const string& to, const char* endpoint, CURL* handle) } } -bool CURLSOAPTransport::setAuth(transport_auth_t authType, const char* username, const char* password) const +bool CURLSOAPTransport::setAuth(transport_auth_t authType, const char* username, const char* password) { if (authType==transport_auth_none) { if (curl_easy_setopt(m_handle,CURLOPT_HTTPAUTH,0)!=CURLE_OK) @@ -367,14 +371,30 @@ void CURLSOAPTransport::send(istream& in) Category& log=Category::getInstance(XMLTOOLING_LOGCAT".SOAPTransport"); Category& log_curl=Category::getInstance(XMLTOOLING_LOGCAT".libcurl"); + string msg; + // By this time, the handle has been prepared with the URL to use and the // caller should have executed any set functions to manipulate it. // Setup standard per-call curl properties. - curl_easy_setopt(m_handle,CURLOPT_POST,1); - curl_easy_setopt(m_handle,CURLOPT_READDATA,&in); - curl_easy_setopt(m_handle,CURLOPT_FILE,&m_stream); curl_easy_setopt(m_handle,CURLOPT_DEBUGDATA,&log_curl); + curl_easy_setopt(m_handle,CURLOPT_FILE,&m_stream); + curl_easy_setopt(m_handle,CURLOPT_POST,1); + if (m_chunked) { + m_headers=curl_slist_append(m_headers,"Transfer-Encoding: chunked"); + curl_easy_setopt(m_handle,CURLOPT_READFUNCTION,&curl_read_hook); + curl_easy_setopt(m_handle,CURLOPT_READDATA,&in); + } + else { + char buf[1024]; + while (in) { + in.read(buf,1024); + msg.append(buf,in.gcount()); + } + curl_easy_setopt(m_handle,CURLOPT_READFUNCTION,NULL); + curl_easy_setopt(m_handle,CURLOPT_POSTFIELDS,msg.c_str()); + curl_easy_setopt(m_handle,CURLOPT_POSTFIELDSIZE,msg.length()); + } char curl_errorbuf[CURL_ERROR_SIZE]; curl_errorbuf[0]=0; @@ -382,7 +402,7 @@ void CURLSOAPTransport::send(istream& in) if (log_curl.isDebugEnabled()) curl_easy_setopt(m_handle,CURLOPT_VERBOSE,1); - // Set request headers (possibly appended by hooks). + // Set request headers. curl_easy_setopt(m_handle,CURLOPT_HTTPHEADER,m_headers); if (m_ssl_callback || m_credResolver || m_trustEngine) { -- 2.1.4