/** * @file llhttpclient.h * @brief Declaration of classes for making HTTP client requests. * * $LicenseInfo:firstyear=2006&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #ifndef LL_LLHTTPCLIENT_H #define LL_LLHTTPCLIENT_H /** * These classes represent the HTTP client framework. */ #include #include // CURLcode #include #include "llassettype.h" #include "llhttpstatuscodes.h" #include "aihttpheaders.h" #include "aicurlperservice.h" class LLUUID; class LLPumpIO; class LLSD; class AIHTTPTimeoutPolicy; class LLBufferArray; class LLChannelDescriptors; class AIStateMachine; class Injector; class AIEngine; extern AIHTTPTimeoutPolicy responderIgnore_timeout; typedef struct _xmlrpc_request* XMLRPC_REQUEST; typedef struct _xmlrpc_value* XMLRPC_VALUE; extern AIEngine gMainThreadEngine; // In Viewer 3 this definition is in indra/newview/lltexturefetch.cpp, // but we need it in two .cpp files, so it's moved here. // // BUG-3323/SH-4375 // *NOTE: This is a heuristic value. Texture fetches have a habit of using a // value of 32MB to indicate 'get the rest of the image'. Certain ISPs and // network equipment get confused when they see this in a Range: header. So, // if the request end is beyond this value, we issue an open-ended Range: // request (e.g. 'Range: -') which seems to fix the problem. static const S32 HTTP_REQUESTS_RANGE_END_MAX = 20000000; // Output parameter of AICurlPrivate::CurlEasyRequest::getResult. // Used in XMLRPCResponder. struct AITransferInfo { AITransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) { } F64 mSizeDownload; F64 mTotalTime; F64 mSpeedDownload; }; // Events generated by AICurlPrivate::BufferedCurlEasyRequest struct AIBufferedCurlEasyRequestEvents { virtual void received_HTTP_header(void) = 0; // For example "HTTP/1.0 200 OK", the first header of a reply. virtual void received_header(std::string const& key, std::string const& value) = 0; // Subsequent headers. virtual void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) = 0; // Transaction completed. }; enum EKeepAlive { no_keep_alive = 0, keep_alive }; enum EDoesAuthentication { no_does_authentication = 0, does_authentication }; enum EAllowCompressedReply { no_allow_compressed_reply = 0, allow_compressed_reply }; #ifdef DEBUG_CURLIO enum EDebugCurl { debug_off = 0, debug_on }; #define DEBUG_CURLIO_PARAM(p) ,p #else #define DEBUG_CURLIO_PARAM(p) #endif class LLHTTPClient { public: /** * @brief This enumeration is for specifying the type of request. */ enum ERequestAction { INVALID, HTTP_HEAD, HTTP_GET, HTTP_PUT, HTTP_POST, HTTP_DELETE, HTTP_MOVE, // Caller will need to set 'Destination' header HTTP_PATCH, HTTP_COPY, REQUEST_ACTION_COUNT }; /** @name Responder base classes */ //@{ /** * @class ResponderBase * @brief Base class for all Responders. * * The life cycle of classes derived from this class is as follows: * They are allocated with new on the line where get(), getByteRange() or post() is called, * and the pointer to the allocated object is then put in a reference counting ResponderPtr. * This ResponderPtr is passed to BufferedCurlEasyRequest::prepRequest which stores it in its * member mResponder. Hence, the life time of a Responder is never longer than its * associated BufferedCurlEasyRequest, however, if everything works correctly, then normally a * responder is deleted in BufferedCurlEasyRequest::processOutput by setting * mReponder to NULL. */ class ResponderBase : public AIBufferedCurlEasyRequestEvents { public: typedef boost::shared_ptr buffer_ptr_t; /** * @brief return true if the status code indicates success. */ static bool isGoodStatus(S32 status) { return((200 <= status) && (status < 300)); } protected: ResponderBase(void); virtual ~ResponderBase(); // Read body from buffer and put it into mContent. If mStatus indicates success, interpret it as LLSD, otherwise copy it as-is. void decode_llsd_body(LLChannelDescriptors const& channels, buffer_ptr_t const& buffer); // Read body from buffer and put it into content. Always copy it as-is. void decode_raw_body(LLChannelDescriptors const& channels, buffer_ptr_t const& buffer, std::string& content); protected: // Associated URL, used for debug output. std::string mURL; // Headers received from the server. AIHTTPReceivedHeaders mReceivedHeaders; // The curl result code. CURLcode mCode; // HTTP status code, if any. S32 mStatus; // Reason for error if mStatus is not good. std::string mReason; // Content interpreted as LLSD. LLSD mContent; // Set when the transaction finished (with or without errors). bool mFinished; public: // Called to set the URL of the current request for this Responder, // used only when printing debug output regarding activity of the Responder. void setURL(std::string const& url); // Accessors. std::string const& getURL(void) const { return mURL; } CURLcode result_code(void) const { return mCode; } protected: // Short cut. void setResult(S32 status, std::string const& reason, LLSD const& content) { mStatus = status; mReason = reason; mContent = content; mFinished = true; } // Call these only from the httpSuccess/httpFailure/httpComplete methods of derived classes. LLSD const& getContent(void) const { return mContent; } // You can just access mReceivedHeaders directly from derived classes, but added this accessor // for convenience because upstream introduced this method as part of a new API. AIHTTPReceivedHeaders const& getResponseHeaders(void) const { // If this fails then you need to add '/*virtual*/ bool needsHeaders(void) const { return true; }' to the most derived class. llassert(needsHeaders()); return mReceivedHeaders; } // Another convenience method to match upstream. std::string dumpResponse(void) const; public: // The next two are public because blocking_request() needs access too. S32 getStatus(void) const { return mStatus; } std::string const& getReason(void) const { return mReason; } public: // Called by BufferedCurlEasyRequest::timed_out or BufferedCurlEasyRequest::processOutput. virtual void finished(CURLcode code, U32 http_status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) = 0; // Return true if the curl thread is done with this transaction. // If this returns true then it is guaranteed that none of the // virtual functions will be called anymore: the curl thread // will not access this object anymore. // Note that normally you don't need to call this function. bool is_finished(void) const { return mFinished; } protected: // AIBufferedCurlEasyRequestEvents // These three events are only actually called for classes that implement a needsHeaders() that returns true. // Called when the "HTTP/1.x " header is received. /*virtual*/ void received_HTTP_header(void) { // It's possible that this page was moved (302), so we already saw headers // from the 302 page and are starting over on the new page now. // Erase all headers EXCEPT the cookies. AIHTTPReceivedHeaders set_cookie_headers; AIHTTPReceivedHeaders::range_type cookies; if (mReceivedHeaders.getValues("set-cookie", cookies)) { for (AIHTTPReceivedHeaders::iterator_type cookie = cookies.first; cookie != cookies.second; ++cookie) { set_cookie_headers.addHeader(cookie->first, cookie->second); } } // Replace headers with just the cookie headers. mReceivedHeaders.swap(set_cookie_headers); } // Called for all remaining headers. /*virtual*/ void received_header(std::string const& key, std::string const& value) { mReceivedHeaders.addHeader(key, value); } // Called when the whole transaction is completed (also the body was received), but before the body is processed. /*virtual*/ void completed_headers(U32 status, std::string const& reason, AITransferInfo* info) { mStatus = status; mReason = reason; completedHeaders(); } // Extract cookie 'key' from mReceivedHeaders and return the string 'key=value', or an empty string if key does not exists. std::string const& get_cookie(std::string const& key); public: // Derived classes that implement completed_headers()/completedHeaders() should return true here. virtual bool needsHeaders(void) const { return false; } // A derived class should return true if curl should close the connection when done. // The default is to keep connections open for possible reuse. virtual bool forbidReuse(void) const { return false; } // A derived class should return true if curl should not follow redirections, but instead pass redirection status codes to the responder. // The default is to follow redirections and not pass them to the responder. virtual bool pass_redirect_status(void) const { return false; } // If this function returns false then we generate an error when a redirect status (300..399) is received. virtual bool redirect_status_ok(void) const { return true; } // Overridden by LLEventPollResponder to return true. virtual bool is_event_poll(void) const { return false; } // Returns the capability type used by this responder. virtual AICapabilityType capability_type(void) const { return cap_other; } // Timeout policy to use. virtual AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const; // The name of the derived responder object. For debugging purposes. virtual char const* getName(void) const = 0; protected: // Derived classes can override this to get the HTML headers that were received, when the message is completed. // Only actually called for classes that implement a needsHeaders() that returns true. virtual void completedHeaders(void) { // The default does nothing. } private: // Used by ResponderPtr. Object is deleted when reference count reaches zero. LLAtomicU32 mReferenceCount; friend void intrusive_ptr_add_ref(ResponderBase* p); // Called by boost::intrusive_ptr when a new copy of a boost::intrusive_ptr is made. friend void intrusive_ptr_release(ResponderBase* p); // Called by boost::intrusive_ptr when a boost::intrusive_ptr is destroyed. // This function must delete the ResponderBase object when the reference count reaches zero. }; // Responders derived from this base class should use HTTPClient::head or HTTPClient::getHeaderOnly. // That will set the curl option CURLOPT_NOBODY so that only headers are received. class ResponderHeadersOnly : public ResponderBase { private: /*virtual*/ bool needsHeaders(void) const { return true; } protected: // ResponderBase event // The responder finished. Do not override this function in derived classes; override completedRaw instead. /*virtual*/ void finished(CURLcode code, U32 http_status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) { mCode = code; mStatus = http_status; mReason = reason; // Allow classes derived from ResponderHeadersOnly to override completedHeaders. completedHeaders(); mFinished = true; } protected: #ifdef SHOW_ASSERT // Responders derived from this class must override completedHeaders. // They may not attempt to override any of the virual functions defined by ResponderBase. // Define those functions here with different parameters in order to cause a compile // warning when a class accidently tries to override them. enum YOU_MAY_ONLY_OVERRIDE_COMPLETED_HEADERS { }; virtual void completedRaw(YOU_MAY_ONLY_OVERRIDE_COMPLETED_HEADERS) { } virtual void httpCompleted(YOU_MAY_ONLY_OVERRIDE_COMPLETED_HEADERS) { } virtual void httpSuccess(YOU_MAY_ONLY_OVERRIDE_COMPLETED_HEADERS) { } virtual void httpFailure(YOU_MAY_ONLY_OVERRIDE_COMPLETED_HEADERS) { } #endif }; /** * @class ResponderWithCompleted * @brief Base class for Responders that implement completed, or completedRaw if the response is not LLSD. */ class ResponderWithCompleted : public ResponderBase { protected: // ResponderBase event // The responder finished. Do not override this function in derived classes; override completedRaw instead. /*virtual*/ void finished(CURLcode code, U32 http_status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer) { mCode = code; mStatus = http_status; mReason = reason; // Allow classes derived from ResponderWithCompleted to override completedRaw // (if not they should override completed or be derived from ResponderWithResult instead). completedRaw(channels, buffer); mFinished = true; } protected: // Events generated by this class. // Derived classes can override this to get the raw data of the body of the HTML message that was received. // The default is to interpret the content as LLSD and call httpCompleted(). virtual void completedRaw(LLChannelDescriptors const& channels, buffer_ptr_t const& buffer); // ... or, derived classes can override this to get LLSD content when the message is completed. // The default aborts, as it should never be called (can't make it pure virtual though, so // classes that override completedRaw don't need to implement this function, too). virtual void httpCompleted(void); public: // Ugly LL API... void completeResult(S32 status, std::string const& reason, LLSD const& content) { mCode = CURLE_OK; setResult(status, reason, content); httpCompleted(); } #ifdef SHOW_ASSERT // Responders derived from this class must override either completedRaw or completed. // They may not attempt to override any of the virual functions defined by ResponderBase. // Define those functions here with different parameters in order to cause a compile // warning when a class accidently tries to override them. enum YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS { }; virtual void httpSuccess(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } virtual void httpFailure(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } #endif }; /** * @class ResponderWithResult * @brief Base class for reponders that expect LLSD in the body of the reply. * * Classes derived from ResponderWithResult must implement result, and either errorWithContent or error. */ class ResponderWithResult : public ResponderBase { protected: // The responder finished. Do not override this function in derived classes; use ResponderWithCompleted instead. /*virtual*/ void finished(CURLcode code, U32 http_status, std::string const& reason, LLChannelDescriptors const& channels, buffer_ptr_t const& buffer); protected: // Events generated by this class. // Derived classes must override this to receive the content of a body upon success. virtual void httpSuccess(void) = 0; // ... or, derived classes can override this to get informed when a bad HTML status code is received. // The default prints the error to llinfos. virtual void httpFailure(void); public: // Called from LLSDMessage::ResponderAdapter::listener. // LLSDMessage::ResponderAdapter is a hack, showing among others by fact that it needs these functions. void failureResult(U32 status, std::string const& reason, LLSD const& content, CURLcode code = CURLE_OK) { mCode = code; setResult(status, reason, content); httpFailure(); } void successResult(LLSD const& content) { mCode = CURLE_OK; setResult(HTTP_OK, "", content); httpSuccess(); } #ifdef SHOW_ASSERT // Responders derived from this class must override result, and either errorWithContent or error. // They may not attempt to override any of the virual functions defined by ResponderWithCompleted. // Define those functions here with different parameter in order to cause a compile // warning when a class accidently tries to override them. enum YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS { }; virtual void completedRaw(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } virtual void httpCompleted(YOU_ARE_DERIVING_FROM_THE_WRONG_CLASS) { } #endif }; /** * @class ResponderIgnoreBody * @brief Base class for responders that ignore the result body. */ class ResponderIgnoreBody : public ResponderWithResult { void httpSuccess(void) { } }; /** * @class ResponderIgnore * @brief Responder that ignores the reply, if any, from the server. */ class ResponderIgnore : public ResponderIgnoreBody { /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return responderIgnore_timeout;} /*virtual*/ char const* getName(void) const { return "ResponderIgnore"; } }; // A Responder is passed around as ResponderPtr, which causes it to automatically // destruct when there are no pointers left pointing to it. typedef boost::intrusive_ptr ResponderPtr; //@} /** General API to request a transfer. */ static void request( std::string const& url, ERequestAction method, Injector* body_injector, ResponderPtr responder, AIHTTPHeaders& headers, AIPerService::Approvement* approved/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug), EKeepAlive keepalive = keep_alive, EDoesAuthentication does_auth = no_does_authentication, EAllowCompressedReply allow_compression = allow_compressed_reply, AIStateMachine* parent = NULL, /*AIStateMachine::state_type*/ U32 new_parent_state = 0, AIEngine* default_engine = &gMainThreadEngine); /** @name non-blocking API */ //@{ static void head(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void head(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; head(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } static bool getByteRange(std::string const& url, AIHTTPHeaders& headers, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static bool getByteRange(std::string const& url, S32 offset, S32 bytes, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; return getByteRange(url, headers, offset, bytes, responder/*,*/ DEBUG_CURLIO_PARAM(debug)); } static void get(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void get(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; get(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } static void get(std::string const& url, LLSD const& query, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void get(std::string const& url, LLSD const& query, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; get(url, query, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } static void put(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void put(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; put(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } static void putRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void putRaw(const std::string& url, const U8* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; putRaw(url, data, size, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void getHeaderOnly(std::string const& url, ResponderHeadersOnly* responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; getHeaderOnly(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } static void patch(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0); static void patch(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0) { AIHTTPHeaders headers; patch(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, parent, new_parent_state); } static void post(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0); static void post(std::string const& url, LLSD const& body, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0) { AIHTTPHeaders headers; post(url, body, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, parent, new_parent_state); } static void post_approved(std::string const& url, LLSD const& body, ResponderPtr responder, AIHTTPHeaders& headers, AIPerService::Approvement* approved/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0); static void post_approved(std::string const& url, LLSD const& body, ResponderPtr responder, AIPerService::Approvement* approved/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive, AIStateMachine* parent = NULL, U32 new_parent_state = 0) { AIHTTPHeaders headers; post_approved(url, body, responder, headers, approved/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive, parent, new_parent_state); } /** Takes ownership of request and deletes it when sent */ static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); static void postXMLRPC(std::string const& url, XMLRPC_REQUEST request, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) { AIHTTPHeaders headers; postXMLRPC(url, request, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); static void postXMLRPC(std::string const& url, char const* method, XMLRPC_VALUE value, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) { AIHTTPHeaders headers; postXMLRPC(url, method, value, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } /** Takes ownership of data and deletes it when sent */ static void postRaw(std::string const& url, const U8* data, S32 size, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); static void postRaw(std::string const& url, const U8* data, S32 size, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) { AIHTTPHeaders headers; postRaw(url, data, size, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); static void postFile(std::string const& url, std::string const& filename, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) { AIHTTPHeaders headers; postFile(url, filename, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive); static void postFile(std::string const& url, const LLUUID& uuid, LLAssetType::EType asset_type, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off), EKeepAlive keepalive = keep_alive) { AIHTTPHeaders headers; postFile(url, uuid, asset_type, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug), keepalive); } static void del(std::string const& url, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void del(std::string const& url, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; del(url, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } ///< sends a DELETE method, but we can't call it delete in c++ /** * @brief Send a MOVE webdav method * * @param url The complete serialized (and escaped) url to get. * @param destination The complete serialized destination url. * @param responder The responder that will handle the result. * @param headers A map of key:value headers to pass to the request * @param timeout The number of seconds to give the server to respond. */ static void move(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void move(std::string const& url, std::string const& destination, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; move(url, destination, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } //@} static void copy(std::string const& url, std::string const& destination, ResponderPtr responder, AIHTTPHeaders& headers/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); static void copy(std::string const& url, std::string const& destination, ResponderPtr responder/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)) { AIHTTPHeaders headers; copy(url, destination, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug)); } /** * @brief Blocking HTTP GET that returns an LLSD map of status and body. * * @param url the complete serialized (and escaped) url to get * @return An LLSD of { 'status':status, 'body':payload } */ static LLSD blockingGet(std::string const& url/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); /** * @brief Blocking HTTP GET that returns the raw body. * * @param url the complete serialized (and escaped) url to get * @param result the target string to write the body to * @return HTTP status */ static U32 blockingGetRaw(const std::string& url, std::string& result/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); /** * @brief Blocking HTTP POST that returns an LLSD map of status and body. * * @param url the complete serialized (and escaped) url to get * @param body the LLSD post body * @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) } */ static LLSD blockingPost(std::string const& url, LLSD const& body/*,*/ DEBUG_CURLIO_PARAM(EDebugCurl debug = debug_off)); }; #endif // LL_LLHTTPCLIENT_H