llurlrequest.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:11k
- /**
- * @file llurlrequest.h
- * @author Phoenix
- * @date 2005-04-21
- * @brief Declaration of url based requests on pipes.
- *
- * $LicenseInfo:firstyear=2005&license=viewergpl$
- *
- * Copyright (c) 2005-2010, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #ifndef LL_LLURLREQUEST_H
- #define LL_LLURLREQUEST_H
- /**
- * This file holds the declaration of useful classes for dealing with
- * url based client requests.
- */
- #include <string>
- #include "lliopipe.h"
- #include "llchainio.h"
- #include "llerror.h"
- extern const std::string CONTEXT_REQUEST;
- extern const std::string CONTEXT_DEST_URI_SD_LABEL;
- extern const std::string CONTEXT_RESPONSE;
- extern const std::string CONTEXT_TRANSFERED_BYTES;
- class LLURLRequestDetail;
- class LLURLRequestComplete;
- /**
- * @class LLURLRequest
- * @brief Class to handle url based requests.
- * @see LLIOPipe
- *
- * Currently, this class is implemented on top of curl. From the
- * vantage of a programmer using this class, you do not care so much,
- * but it's useful to know since in order to accomplish 'non-blocking'
- * behavior, we have to use a more expensive curl interface which can
- * still block if the server enters a half-accepted state. It would be
- * worth the time and effort to eventually port this to a raw client
- * socket.
- */
- class LLURLRequest : public LLIOPipe
- {
- LOG_CLASS(LLURLRequest);
- 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
- REQUEST_ACTION_COUNT
- };
- /**
- * @brief Turn the requst action into an http verb.
- */
- static std::string actionAsVerb(ERequestAction action);
- /**
- * @brief Constructor.
- *
- * @param action One of the ERequestAction enumerations.
- */
- LLURLRequest(ERequestAction action);
- /**
- * @brief Constructor.
- *
- * @param action One of the ERequestAction enumerations.
- * @param url The url of the request. It should already be encoded.
- */
- LLURLRequest(ERequestAction action, const std::string& url);
- /**
- * @brief Destructor.
- */
- virtual ~LLURLRequest();
- /* @name Instance methods
- */
- //@{
- /**
- * @brief Set the url for the request
- *
- * This method assumes the url is encoded appropriately for the
- * request.
- * The url must be set somehow before the first call to process(),
- * or the url will not be set correctly.
- *
- */
- void setURL(const std::string& url);
- /**
- * @brief Add a header to the http post.
- *
- * The header must be correctly formatted for HTTP requests. This
- * provides a raw interface if you know what kind of request you
- * will be making during construction of this instance. All
- * required headers will be automatically constructed, so this is
- * usually useful for encoding parameters.
- */
- void addHeader(const char* header);
- /**
- * @brief Check remote server certificate signed by a known root CA.
- *
- * Set whether request will check that remote server
- * certificates are signed by a known root CA when using HTTPS.
- */
- void checkRootCertificate(bool check);
- /**
- * @brief Return at most size bytes of body.
- *
- * If the body had more bytes than this limit, they will not be
- * returned and the connection closed. In this case, STATUS_STOP
- * will be passed to responseStatus();
- */
- void setBodyLimit(U32 size);
- /**
- * @brief Set a completion callback for this URLRequest.
- *
- * The callback is added to this URLRequet's pump when either the
- * entire buffer is known or an error like timeout or connection
- * refused has happened. In the case of a complete transfer, this
- * object builds a response chain such that the callback and the
- * next process consumer get to read the output.
- *
- * This setup is a little fragile since the url request consumer
- * might not just read the data - it may do a channel change,
- * which invalidates the input to the callback, but it works well
- * in practice.
- */
- void setCallback(LLURLRequestComplete* callback);
- //@}
- /* @name LLIOPipe virtual implementations
- */
- /**
- * @ brief Turn off (or on) the CURLOPT_PROXY header.
- */
- void useProxy(bool use_proxy);
- /**
- * @ brief Set the CURLOPT_PROXY header to the given value.
- */
- void useProxy(const std::string& proxy);
- public:
- /**
- * @brief Give this pipe a chance to handle a generated error
- */
- virtual EStatus handleError(EStatus status, LLPumpIO* pump);
-
- protected:
- /**
- * @brief Process the data in buffer
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
- protected:
- enum EState
- {
- STATE_INITIALIZED,
- STATE_WAITING_FOR_RESPONSE,
- STATE_PROCESSING_RESPONSE,
- STATE_HAVE_RESPONSE,
- };
- EState mState;
- ERequestAction mAction;
- LLURLRequestDetail* mDetail;
- LLIOPipe::ptr_t mCompletionCallback;
- S32 mRequestTransferedBytes;
- S32 mResponseTransferedBytes;
- private:
- /**
- * @brief Initialize the object. Called during construction.
- */
- void initialize();
- /**
- * @brief Handle action specific url request configuration.
- *
- * @return Returns true if this is configured.
- */
- bool configure();
- /**
- * @brief Download callback method.
- */
- static size_t downCallback(
- char* data,
- size_t size,
- size_t nmemb,
- void* user);
- /**
- * @brief Upload callback method.
- */
- static size_t upCallback(
- char* data,
- size_t size,
- size_t nmemb,
- void* user);
- /**
- * @brief Declaration of unimplemented method to prevent copy
- * construction.
- */
- LLURLRequest(const LLURLRequest&);
- };
- /**
- * @class LLContextURLExtractor
- * @brief This class unpacks the url out of a agent usher service so
- * it can be packed into a LLURLRequest object.
- * @see LLIOPipe
- *
- * This class assumes that the context is a map that contains an entry
- * named CONTEXT_DEST_URI_SD_LABEL.
- */
- class LLContextURLExtractor : public LLIOPipe
- {
- public:
- LLContextURLExtractor(LLURLRequest* req) : mRequest(req) {}
- ~LLContextURLExtractor() {}
- protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
- protected:
- LLURLRequest* mRequest;
- };
- /**
- * @class LLURLRequestComplete
- * @brief Class which can optionally be used with an LLURLRequest to
- * get notification when the url request is complete.
- */
- class LLURLRequestComplete : public LLIOPipe
- {
- public:
-
- // Called once for each header received, except status lines
- virtual void header(const std::string& header, const std::string& value);
- // May be called more than once, particularly for redirects and proxy madness.
- // Ex. a 200 for a connection to https through a proxy, followed by the "real" status
- // a 3xx for a redirect followed by a "real" status, or more redirects.
- virtual void httpStatus(U32 status, const std::string& reason) { }
- virtual void complete(
- const LLChannelDescriptors& channels,
- const buffer_ptr_t& buffer);
- /**
- * @brief This method is called when we got a valid response.
- *
- * It is up to class implementers to do something useful here.
- */
- virtual void response(
- const LLChannelDescriptors& channels,
- const buffer_ptr_t& buffer);
- /**
- * @brief This method is called if there was no response.
- *
- * It is up to class implementers to do something useful here.
- */
- virtual void noResponse();
- /**
- * @brief This method will be called by the LLURLRequest object.
- *
- * If this is set to STATUS_OK or STATUS_STOP, then the transfer
- * is asssumed to have worked. This will lead to calling response()
- * on the next call to process(). Otherwise, this object will call
- * noResponse() on the next call to process.
- * @param status The status of the URLRequest.
- */
- void responseStatus(EStatus status);
- // constructor & destructor.
- LLURLRequestComplete();
- virtual ~LLURLRequestComplete();
- protected:
- /* @name LLIOPipe virtual implementations
- */
- //@{
- /**
- * @brief Process the data in buffer
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
- // value to note if we actually got the response. This value
- // depends on correct useage from the LLURLRequest instance.
- EStatus mRequestStatus;
- };
- /**
- * @class LLURLRequestClientFactory
- * @brief Template class to build url request based client chains
- *
- * This class eases construction of a basic sd rpc client. Here is an
- * example of it's use:
- * <code>
- * class LLUsefulService : public LLService { ... }<br>
- * LLService::registerCreator(<br>
- * "useful",<br>
- * LLService::creator_t(new LLURLRequestClientFactory<LLUsefulService>))<br>
- * </code>
- *
- * This class should work, but I never got around to using/testing it.
- *
- */
- #if 0
- template<class Client>
- class LLURLRequestClientFactory : public LLChainIOFactory
- {
- public:
- LLURLRequestClientFactory(LLURLRequest::ERequestAction action) {}
- LLURLRequestClientFactory(
- LLURLRequest::ERequestAction action,
- const std::string& fixed_url) :
- mAction(action),
- mURL(fixed_url)
- {
- }
- virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const
- {
- lldebugs << "LLURLRequestClientFactory::build" << llendl;
- LLIOPipe::ptr_t service(new Client);
- chain.push_back(service);
- LLURLRequest* http(new LLURLRequest(mAction));
- LLIOPipe::ptr_t http_pipe(http);
- // *FIX: how do we know the content type?
- //http->addHeader("Content-Type: text/llsd");
- if(mURL.empty())
- {
- chain.push_back(LLIOPipe::ptr_t(new LLContextURLExtractor(http)));
- }
- else
- {
- http->setURL(mURL);
- }
- chain.push_back(http_pipe);
- chain.push_back(service);
- return true;
- }
- protected:
- LLURLRequest::ERequestAction mAction;
- std::string mURL;
- };
- #endif
- /**
- * External constants
- */
- extern const std::string CONTEXT_DEST_URI_SD_LABEL;
- #endif // LL_LLURLREQUEST_H