HTTP Proxy, PUT & POST, unit tests and refactoring.
Implemented/modified PUT & POST to not used chunked encoding for the request. Made the unit test much happier and probably a better thing for the pipeline. Have a cheesy static & dynamic proxy capability using both local options and a way to wire into LLProxy in llmessages. Not a clean thing but it will get the proxy path working with both socks5 & http proxies. Refactoring to get rid of unneeded library handler and unified an HttpStatus return for all requests. Big batch of code removed as a result of that and more is possible as well as some syscall avoidance with a bit more work. Boosted the unit tests for simple PUT & POST test which revealed the test harness does *not* like chunked encoding so we'll avoid it for now (and don't really need it in any of our schemes).master
parent
24e16e1632
commit
7adeb39237
|
|
@ -10,12 +10,14 @@ include(OpenSSL)
|
|||
include(ZLIB)
|
||||
include(LLCoreHttp)
|
||||
include(LLAddBuildTest)
|
||||
include(LLMessage)
|
||||
include(LLCommon)
|
||||
include(Tut)
|
||||
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include_directories(
|
||||
${LLMESSAGE_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LLCOREHTTP_INCLUDE_DIRS}
|
||||
)
|
||||
|
|
@ -31,6 +33,7 @@ set(llcorehttp_SOURCE_FILES
|
|||
_httpopcancel.cpp
|
||||
_httpoperation.cpp
|
||||
_httpoprequest.cpp
|
||||
_httpopsetget.cpp
|
||||
_httpopsetpriority.cpp
|
||||
_httppolicy.cpp
|
||||
_httppolicyglobal.cpp
|
||||
|
|
@ -54,6 +57,7 @@ set(llcorehttp_HEADER_FILES
|
|||
_httpopcancel.h
|
||||
_httpoperation.h
|
||||
_httpoprequest.h
|
||||
_httpopsetget.h
|
||||
_httpopsetpriority.h
|
||||
_httppolicy.h
|
||||
_httppolicyglobal.h
|
||||
|
|
@ -113,6 +117,7 @@ if (LL_TESTS)
|
|||
set(test_libs
|
||||
${LLCOREHTTP_LIBRARIES}
|
||||
${WINDOWS_LIBRARIES}
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${GOOGLEMOCK_LIBRARIES}
|
||||
${CURL_LIBRARIES}
|
||||
|
|
|
|||
|
|
@ -66,17 +66,6 @@ void HttpOpCancel::stageFromRequest(HttpService * service)
|
|||
}
|
||||
|
||||
|
||||
void HttpOpCancel::visitNotifier(HttpRequest * request)
|
||||
{
|
||||
if (mLibraryHandler)
|
||||
{
|
||||
HttpResponse * response = new HttpResponse();
|
||||
mLibraryHandler->onCompleted(static_cast<HttpHandle>(this), response);
|
||||
response->release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace LLCore
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -59,13 +59,10 @@ private:
|
|||
|
||||
public:
|
||||
virtual void stageFromRequest(HttpService *);
|
||||
|
||||
virtual void visitNotifier(HttpRequest * request);
|
||||
|
||||
public:
|
||||
// Request data
|
||||
HttpHandle mHandle;
|
||||
|
||||
}; // end class HttpOpCancel
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,6 @@ namespace LLCore
|
|||
HttpOperation::HttpOperation()
|
||||
: LLCoreInt::RefCounted(true),
|
||||
mReplyQueue(NULL),
|
||||
mLibraryHandler(NULL),
|
||||
mUserHandler(NULL),
|
||||
mReqPolicy(HttpRequest::DEFAULT_POLICY_ID),
|
||||
mReqPriority(0U)
|
||||
|
|
@ -57,13 +56,12 @@ HttpOperation::HttpOperation()
|
|||
|
||||
HttpOperation::~HttpOperation()
|
||||
{
|
||||
setHandlers(NULL, NULL, NULL);
|
||||
setReplyPath(NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
void HttpOperation::setHandlers(HttpReplyQueue * reply_queue,
|
||||
HttpHandler * lib_handler,
|
||||
HttpHandler * user_handler)
|
||||
void HttpOperation::setReplyPath(HttpReplyQueue * reply_queue,
|
||||
HttpHandler * user_handler)
|
||||
{
|
||||
if (reply_queue != mReplyQueue)
|
||||
{
|
||||
|
|
@ -80,9 +78,6 @@ void HttpOperation::setHandlers(HttpReplyQueue * reply_queue,
|
|||
mReplyQueue = reply_queue;
|
||||
}
|
||||
|
||||
// Not refcounted
|
||||
mLibraryHandler = lib_handler;
|
||||
|
||||
// Not refcounted
|
||||
mUserHandler = user_handler;
|
||||
}
|
||||
|
|
@ -121,11 +116,12 @@ void HttpOperation::stageFromActive(HttpService *)
|
|||
|
||||
void HttpOperation::visitNotifier(HttpRequest *)
|
||||
{
|
||||
if (mLibraryHandler)
|
||||
if (mUserHandler)
|
||||
{
|
||||
HttpResponse * response = new HttpResponse();
|
||||
|
||||
mLibraryHandler->onCompleted(static_cast<HttpHandle>(this), response);
|
||||
response->setStatus(mStatus);
|
||||
mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);
|
||||
|
||||
response->release();
|
||||
}
|
||||
|
|
@ -142,7 +138,7 @@ HttpStatus HttpOperation::cancel()
|
|||
|
||||
void HttpOperation::addAsReply()
|
||||
{
|
||||
if (mReplyQueue && mLibraryHandler)
|
||||
if (mReplyQueue)
|
||||
{
|
||||
addRef();
|
||||
mReplyQueue->addOp(this);
|
||||
|
|
|
|||
|
|
@ -80,9 +80,8 @@ private:
|
|||
void operator=(const HttpOperation &); // Not defined
|
||||
|
||||
public:
|
||||
void setHandlers(HttpReplyQueue * reply_queue,
|
||||
HttpHandler * lib_handler,
|
||||
HttpHandler * user_handler);
|
||||
void setReplyPath(HttpReplyQueue * reply_queue,
|
||||
HttpHandler * handler);
|
||||
|
||||
HttpHandler * getUserHandler() const
|
||||
{
|
||||
|
|
@ -102,13 +101,15 @@ protected:
|
|||
|
||||
protected:
|
||||
HttpReplyQueue * mReplyQueue; // Have refcount
|
||||
HttpHandler * mLibraryHandler; // Have refcount
|
||||
HttpHandler * mUserHandler; // Have refcount
|
||||
HttpHandler * mUserHandler;
|
||||
|
||||
public:
|
||||
// Request Data
|
||||
HttpRequest::policy_t mReqPolicy;
|
||||
HttpRequest::priority_t mReqPriority;
|
||||
|
||||
|
||||
// Reply Data
|
||||
HttpStatus mStatus;
|
||||
}; // end class HttpOperation
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "_httplibcurl.h"
|
||||
|
||||
#include "llhttpstatuscodes.h"
|
||||
#include "llproxy.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -207,7 +208,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
|
|||
{
|
||||
static const HttpStatus partial_content(HTTP_PARTIAL_CONTENT, HE_SUCCESS);
|
||||
|
||||
if (mLibraryHandler)
|
||||
if (mUserHandler)
|
||||
{
|
||||
HttpResponse * response = new HttpResponse();
|
||||
response->setStatus(mStatus);
|
||||
|
|
@ -219,7 +220,7 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
|
|||
response->setRange(mReplyOffset, mReplyLength);
|
||||
}
|
||||
|
||||
mLibraryHandler->onCompleted(static_cast<HttpHandle>(this), response);
|
||||
mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);
|
||||
|
||||
response->release();
|
||||
}
|
||||
|
|
@ -304,6 +305,39 @@ HttpStatus HttpOpRequest::setupPost(HttpRequest::policy_t policy_id,
|
|||
}
|
||||
|
||||
|
||||
HttpStatus HttpOpRequest::setupPut(HttpRequest::policy_t policy_id,
|
||||
HttpRequest::priority_t priority,
|
||||
const std::string & url,
|
||||
BufferArray * body,
|
||||
HttpOptions * options,
|
||||
HttpHeaders * headers)
|
||||
{
|
||||
HttpStatus status;
|
||||
|
||||
mProcFlags = 0;
|
||||
mReqPolicy = policy_id;
|
||||
mReqPriority = priority;
|
||||
mReqMethod = HOR_PUT;
|
||||
mReqURL = url;
|
||||
if (body)
|
||||
{
|
||||
body->addRef();
|
||||
mReqBody = body;
|
||||
}
|
||||
if (headers && ! mReqHeaders)
|
||||
{
|
||||
headers->addRef();
|
||||
mReqHeaders = headers;
|
||||
}
|
||||
if (options && ! mReqOptions)
|
||||
{
|
||||
mReqOptions = new HttpOptions(*options);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
||||
{
|
||||
// Scrub transport and result data for retried op case
|
||||
|
|
@ -346,8 +380,6 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
|
||||
// *FIXME: Need to deal with proxy setup...
|
||||
// curl_easy_setopt(handle, CURLOPT_PROXY, "");
|
||||
|
||||
// *FIXME: Revisit this old DNS timeout setting - may no longer be valid
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
|
||||
|
|
@ -361,18 +393,31 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
|
||||
std::string opt_value;
|
||||
const std::string * opt_value(NULL);
|
||||
if (policy.get(HttpRequest::GP_CA_PATH, opt_value))
|
||||
{
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, opt_value.c_str());
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, opt_value->c_str());
|
||||
}
|
||||
if (policy.get(HttpRequest::GP_CA_FILE, opt_value))
|
||||
{
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, opt_value.c_str());
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, opt_value->c_str());
|
||||
}
|
||||
if (policy.get(HttpRequest::GP_HTTP_PROXY, opt_value))
|
||||
{
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, opt_value.c_str());
|
||||
if (*opt_value == "LLProxy")
|
||||
{
|
||||
// Use the viewer-based thread-safe API which has a
|
||||
// fast/safe check for proxy enable. Would like to
|
||||
// encapsulate this someway...
|
||||
LLProxy::getInstance()->applyProxySettings(mCurlHandle);
|
||||
}
|
||||
else
|
||||
{
|
||||
// *TODO: This is fine for now but get fuller socks/
|
||||
// authentication thing going later....
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, opt_value->c_str());
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
|
||||
}
|
||||
}
|
||||
|
||||
switch (mReqMethod)
|
||||
|
|
@ -394,7 +439,6 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
}
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL));
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
|
||||
mCurlHeaders = curl_slist_append(mCurlHeaders, "Transfer-Encoding: chunked");
|
||||
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
|
||||
}
|
||||
break;
|
||||
|
|
@ -409,7 +453,6 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
|
|||
}
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
|
||||
curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
|
||||
mCurlHeaders = curl_slist_append(mCurlHeaders, "Transfer-Encoding: chunked");
|
||||
mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
|
||||
mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
|
||||
mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
|
||||
|
|
|
|||
|
|
@ -91,6 +91,13 @@ public:
|
|||
HttpOptions * options,
|
||||
HttpHeaders * headers);
|
||||
|
||||
HttpStatus setupPut(HttpRequest::policy_t policy_id,
|
||||
HttpRequest::priority_t priority,
|
||||
const std::string & url,
|
||||
BufferArray * body,
|
||||
HttpOptions * options,
|
||||
HttpHeaders * headers);
|
||||
|
||||
HttpStatus prepareRequest(HttpService * service);
|
||||
|
||||
virtual HttpStatus cancel();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* @file _httpopsetget.cpp
|
||||
* @brief Definitions for internal class HttpOpSetGet
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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$
|
||||
*/
|
||||
|
||||
#include "_httpopsetget.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
|
||||
#include "httpcommon.h"
|
||||
#include "httphandler.h"
|
||||
#include "httpresponse.h"
|
||||
|
||||
#include "_httprequestqueue.h"
|
||||
#include "_httpreplyqueue.h"
|
||||
#include "_httpservice.h"
|
||||
#include "_httppolicy.h"
|
||||
#include "_httplibcurl.h"
|
||||
|
||||
|
||||
namespace LLCore
|
||||
{
|
||||
|
||||
|
||||
// ==================================
|
||||
// HttpOpSetget
|
||||
// ==================================
|
||||
|
||||
|
||||
HttpOpSetGet::HttpOpSetGet()
|
||||
: HttpOperation(),
|
||||
mIsGlobal(false),
|
||||
mDoSet(false),
|
||||
mSetting(-1), // Nothing requested
|
||||
mLongValue(0L)
|
||||
{}
|
||||
|
||||
|
||||
HttpOpSetGet::~HttpOpSetGet()
|
||||
{}
|
||||
|
||||
|
||||
void HttpOpSetGet::setupGet(HttpRequest::EGlobalPolicy setting)
|
||||
{
|
||||
mIsGlobal = true;
|
||||
mSetting = setting;
|
||||
}
|
||||
|
||||
|
||||
void HttpOpSetGet::setupSet(HttpRequest::EGlobalPolicy setting, const std::string & value)
|
||||
{
|
||||
mIsGlobal = true;
|
||||
mDoSet = true;
|
||||
mSetting = setting;
|
||||
mStrValue = value;
|
||||
}
|
||||
|
||||
|
||||
void HttpOpSetGet::stageFromRequest(HttpService * service)
|
||||
{
|
||||
HttpPolicyGlobal & pol_opt(service->getPolicy().getGlobalOptions());
|
||||
HttpRequest::EGlobalPolicy setting(static_cast<HttpRequest::EGlobalPolicy>(mSetting));
|
||||
|
||||
if (mDoSet)
|
||||
{
|
||||
mStatus = pol_opt.set(setting, mStrValue);
|
||||
}
|
||||
if (mStatus)
|
||||
{
|
||||
const std::string * value;
|
||||
if ((mStatus = pol_opt.get(setting, value)))
|
||||
{
|
||||
mStrValue = *value;
|
||||
}
|
||||
}
|
||||
|
||||
addAsReply();
|
||||
}
|
||||
|
||||
|
||||
} // end namespace LLCore
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* @file _httpopsetget.h
|
||||
* @brief Internal declarations for the HttpOpSetGet subclass
|
||||
*
|
||||
* $LicenseInfo:firstyear=2012&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, 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 _LLCORE_HTTP_OPSETGET_H_
|
||||
#define _LLCORE_HTTP_OPSETGET_H_
|
||||
|
||||
|
||||
#include "linden_common.h" // Modifies curl/curl.h interfaces
|
||||
|
||||
#include "httpcommon.h"
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
#include "_httpoperation.h"
|
||||
#include "_refcounted.h"
|
||||
|
||||
|
||||
namespace LLCore
|
||||
{
|
||||
|
||||
|
||||
/// HttpOpSetGet requests dynamic changes to policy and
|
||||
/// configuration settings.
|
||||
|
||||
class HttpOpSetGet : public HttpOperation
|
||||
{
|
||||
public:
|
||||
HttpOpSetGet();
|
||||
virtual ~HttpOpSetGet();
|
||||
|
||||
private:
|
||||
HttpOpSetGet(const HttpOpSetGet &); // Not defined
|
||||
void operator=(const HttpOpSetGet &); // Not defined
|
||||
|
||||
public:
|
||||
void setupGet(HttpRequest::EGlobalPolicy setting);
|
||||
void setupSet(HttpRequest::EGlobalPolicy setting, const std::string & value);
|
||||
|
||||
virtual void stageFromRequest(HttpService *);
|
||||
|
||||
public:
|
||||
// Request data
|
||||
bool mIsGlobal;
|
||||
bool mDoSet;
|
||||
int mSetting;
|
||||
long mLongValue;
|
||||
std::string mStrValue;
|
||||
|
||||
}; // end class HttpOpSetGet
|
||||
|
||||
|
||||
} // end namespace LLCore
|
||||
|
||||
#endif // _LLCORE_HTTP_OPSETGET_H_
|
||||
|
||||
|
|
@ -60,18 +60,4 @@ void HttpOpSetPriority::stageFromRequest(HttpService * service)
|
|||
}
|
||||
|
||||
|
||||
void HttpOpSetPriority::visitNotifier(HttpRequest * request)
|
||||
{
|
||||
if (mLibraryHandler)
|
||||
{
|
||||
HttpResponse * response = new HttpResponse();
|
||||
|
||||
response->setStatus(mStatus);
|
||||
mLibraryHandler->onCompleted(static_cast<HttpHandle>(this), response);
|
||||
|
||||
response->release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace LLCore
|
||||
|
|
|
|||
|
|
@ -56,10 +56,8 @@ private:
|
|||
public:
|
||||
virtual void stageFromRequest(HttpService *);
|
||||
|
||||
virtual void visitNotifier(HttpRequest * request);
|
||||
|
||||
protected:
|
||||
HttpStatus mStatus;
|
||||
// Request Data
|
||||
HttpHandle mHandle;
|
||||
HttpRequest::priority_t mPriority;
|
||||
}; // end class HttpOpSetPriority
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ HttpPolicy::~HttpPolicy()
|
|||
}
|
||||
|
||||
|
||||
void HttpPolicy::setPolicies(const HttpPolicyGlobal & global)
|
||||
{
|
||||
mGlobalOptions = global;
|
||||
}
|
||||
|
||||
|
||||
void HttpPolicy::addOp(HttpOpRequest * op)
|
||||
{
|
||||
const int policy_class(op->mReqPolicy);
|
||||
|
|
|
|||
|
|
@ -95,7 +95,9 @@ public:
|
|||
{
|
||||
return mGlobalOptions;
|
||||
}
|
||||
|
||||
|
||||
void setPolicies(const HttpPolicyGlobal & global);
|
||||
|
||||
protected:
|
||||
struct State
|
||||
{
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace LLCore
|
|||
|
||||
|
||||
HttpPolicyGlobal::HttpPolicyGlobal()
|
||||
: mValidMask(0UL),
|
||||
: mSetMask(0UL),
|
||||
mConnectionLimit(32L)
|
||||
{}
|
||||
|
||||
|
|
@ -41,6 +41,20 @@ HttpPolicyGlobal::~HttpPolicyGlobal()
|
|||
{}
|
||||
|
||||
|
||||
HttpPolicyGlobal & HttpPolicyGlobal::operator=(const HttpPolicyGlobal & other)
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
mSetMask = other.mSetMask;
|
||||
mConnectionLimit = other.mConnectionLimit;
|
||||
mCAPath = other.mCAPath;
|
||||
mCAFile = other.mCAFile;
|
||||
mHttpProxy = other.mHttpProxy;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
HttpStatus HttpPolicyGlobal::set(HttpRequest::EGlobalPolicy opt, long value)
|
||||
{
|
||||
switch (opt)
|
||||
|
|
@ -53,7 +67,7 @@ HttpStatus HttpPolicyGlobal::set(HttpRequest::EGlobalPolicy opt, long value)
|
|||
return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);
|
||||
}
|
||||
|
||||
mValidMask |= 1UL << int(opt);
|
||||
mSetMask |= 1UL << int(opt);
|
||||
return HttpStatus();
|
||||
}
|
||||
|
||||
|
|
@ -78,7 +92,7 @@ HttpStatus HttpPolicyGlobal::set(HttpRequest::EGlobalPolicy opt, const std::stri
|
|||
return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);
|
||||
}
|
||||
|
||||
mValidMask |= 1UL << int(opt);
|
||||
mSetMask |= 1UL << int(opt);
|
||||
return HttpStatus();
|
||||
}
|
||||
|
||||
|
|
@ -90,7 +104,7 @@ HttpStatus HttpPolicyGlobal::get(HttpRequest::EGlobalPolicy opt, long & value)
|
|||
switch (opt)
|
||||
{
|
||||
case HttpRequest::GP_CONNECTION_LIMIT:
|
||||
if (! (mValidMask & (1UL << int(opt))))
|
||||
if (! (mSetMask & (1UL << int(opt))))
|
||||
return not_set;
|
||||
value = mConnectionLimit;
|
||||
break;
|
||||
|
|
@ -103,28 +117,28 @@ HttpStatus HttpPolicyGlobal::get(HttpRequest::EGlobalPolicy opt, long & value)
|
|||
}
|
||||
|
||||
|
||||
HttpStatus HttpPolicyGlobal::get(HttpRequest::EGlobalPolicy opt, std::string & value)
|
||||
HttpStatus HttpPolicyGlobal::get(HttpRequest::EGlobalPolicy opt, const std::string *& value)
|
||||
{
|
||||
static const HttpStatus not_set(HttpStatus::LLCORE, HE_OPT_NOT_SET);
|
||||
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case HttpRequest::GP_CA_PATH:
|
||||
if (! (mValidMask & (1UL << int(opt))))
|
||||
if (! (mSetMask & (1UL << int(opt))))
|
||||
return not_set;
|
||||
value = mCAPath;
|
||||
value = &mCAPath;
|
||||
break;
|
||||
|
||||
case HttpRequest::GP_CA_FILE:
|
||||
if (! (mValidMask & (1UL << int(opt))))
|
||||
if (! (mSetMask & (1UL << int(opt))))
|
||||
return not_set;
|
||||
value = mCAFile;
|
||||
value = &mCAFile;
|
||||
break;
|
||||
|
||||
case HttpRequest::GP_HTTP_PROXY:
|
||||
if (! (mValidMask & (1UL << int(opt))))
|
||||
if (! (mSetMask & (1UL << int(opt))))
|
||||
return not_set;
|
||||
value = mHttpProxy;
|
||||
value = &mHttpProxy;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -40,18 +40,19 @@ public:
|
|||
HttpPolicyGlobal();
|
||||
~HttpPolicyGlobal();
|
||||
|
||||
HttpPolicyGlobal & operator=(const HttpPolicyGlobal &);
|
||||
|
||||
private:
|
||||
HttpPolicyGlobal(const HttpPolicyGlobal &); // Not defined
|
||||
void operator=(const HttpPolicyGlobal &); // Not defined
|
||||
|
||||
public:
|
||||
HttpStatus set(HttpRequest::EGlobalPolicy opt, long value);
|
||||
HttpStatus set(HttpRequest::EGlobalPolicy opt, const std::string & value);
|
||||
HttpStatus get(HttpRequest::EGlobalPolicy opt, long & value);
|
||||
HttpStatus get(HttpRequest::EGlobalPolicy opt, std::string & value);
|
||||
HttpStatus get(HttpRequest::EGlobalPolicy opt, const std::string *& value);
|
||||
|
||||
public:
|
||||
unsigned long mValidMask;
|
||||
unsigned long mSetMask;
|
||||
long mConnectionLimit;
|
||||
std::string mCAPath;
|
||||
std::string mCAFile;
|
||||
|
|
|
|||
|
|
@ -79,11 +79,8 @@ HttpService::~HttpService()
|
|||
mTransport = NULL;
|
||||
}
|
||||
|
||||
if (mPolicy)
|
||||
{
|
||||
delete mPolicy;
|
||||
mPolicy = NULL;
|
||||
}
|
||||
delete mPolicy;
|
||||
mPolicy = NULL;
|
||||
|
||||
if (mThread)
|
||||
{
|
||||
|
|
@ -145,6 +142,10 @@ void HttpService::startThread()
|
|||
{
|
||||
mThread->release();
|
||||
}
|
||||
|
||||
// Push current policy definitions
|
||||
mPolicy->setPolicies(mPolicyGlobal);
|
||||
|
||||
mThread = new LLCoreInt::HttpThread(boost::bind(&HttpService::threadRun, this, _1));
|
||||
mThread->addRef(); // Need an explicit reference, implicit one is used internally
|
||||
sState = RUNNING;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "httpcommon.h"
|
||||
#include "httprequest.h"
|
||||
#include "_httppolicyglobal.h"
|
||||
|
||||
|
||||
namespace LLCoreInt
|
||||
|
|
@ -157,6 +158,11 @@ public:
|
|||
{
|
||||
return *mTransport;
|
||||
}
|
||||
|
||||
HttpPolicyGlobal & getGlobalOptions()
|
||||
{
|
||||
return mPolicyGlobal;
|
||||
}
|
||||
|
||||
protected:
|
||||
void threadRun(LLCoreInt::HttpThread * thread);
|
||||
|
|
@ -173,11 +179,11 @@ protected:
|
|||
|
||||
// === calling-thread-only data ===
|
||||
LLCoreInt::HttpThread * mThread;
|
||||
|
||||
HttpPolicyGlobal mPolicyGlobal;
|
||||
|
||||
// === working-thread-only data ===
|
||||
HttpPolicy * mPolicy; // Simple pointer, has ownership
|
||||
HttpLibcurl * mTransport; // Simple pointer, has ownership
|
||||
|
||||
}; // end class HttpService
|
||||
|
||||
} // end namespace LLCore
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "_httpoprequest.h"
|
||||
#include "_httpopsetpriority.h"
|
||||
#include "_httpopcancel.h"
|
||||
#include "_httpopsetget.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
|
||||
|
|
@ -48,39 +49,6 @@ bool has_inited(false);
|
|||
namespace LLCore
|
||||
{
|
||||
|
||||
// ====================================
|
||||
// InternalHandler Implementation
|
||||
// ====================================
|
||||
|
||||
|
||||
class HttpRequest::InternalHandler : public HttpHandler
|
||||
{
|
||||
public:
|
||||
InternalHandler(HttpRequest & request)
|
||||
: mRequest(request)
|
||||
{}
|
||||
|
||||
protected:
|
||||
InternalHandler(const InternalHandler &); // Not defined
|
||||
void operator=(const InternalHandler &); // Not defined
|
||||
|
||||
public:
|
||||
void onCompleted(HttpHandle handle, HttpResponse * response)
|
||||
{
|
||||
HttpOperation * op(static_cast<HttpOperation *>(handle));
|
||||
HttpHandler * user_handler(op->getUserHandler());
|
||||
if (user_handler)
|
||||
{
|
||||
user_handler->onCompleted(handle, response);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
HttpRequest & mRequest;
|
||||
|
||||
}; // end class HttpRequest::InternalHandler
|
||||
|
||||
|
||||
// ====================================
|
||||
// HttpRequest Implementation
|
||||
// ====================================
|
||||
|
|
@ -92,15 +60,12 @@ HttpRequest::policy_t HttpRequest::sNextPolicyID(1);
|
|||
HttpRequest::HttpRequest()
|
||||
: //HttpHandler(),
|
||||
mReplyQueue(NULL),
|
||||
mRequestQueue(NULL),
|
||||
mSelfHandler(NULL)
|
||||
mRequestQueue(NULL)
|
||||
{
|
||||
mRequestQueue = HttpRequestQueue::instanceOf();
|
||||
mRequestQueue->addRef();
|
||||
|
||||
mReplyQueue = new HttpReplyQueue();
|
||||
|
||||
mSelfHandler = new InternalHandler(*this);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -117,9 +82,6 @@ HttpRequest::~HttpRequest()
|
|||
mReplyQueue->release();
|
||||
mReplyQueue = NULL;
|
||||
}
|
||||
|
||||
delete mSelfHandler;
|
||||
mSelfHandler = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -132,7 +94,7 @@ HttpStatus HttpRequest::setPolicyGlobalOption(EGlobalPolicy opt, long value)
|
|||
{
|
||||
// *FIXME: Fail if thread is running.
|
||||
|
||||
return HttpService::instanceOf()->getPolicy().getGlobalOptions().set(opt, value);
|
||||
return HttpService::instanceOf()->getGlobalOptions().set(opt, value);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -140,7 +102,7 @@ HttpStatus HttpRequest::setPolicyGlobalOption(EGlobalPolicy opt, const std::stri
|
|||
{
|
||||
// *FIXME: Fail if thread is running.
|
||||
|
||||
return HttpService::instanceOf()->getPolicy().getGlobalOptions().set(opt, value);
|
||||
return HttpService::instanceOf()->getGlobalOptions().set(opt, value);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -192,7 +154,7 @@ HttpHandle HttpRequest::requestGetByteRange(policy_t policy_id,
|
|||
mLastReqStatus = status;
|
||||
return handle;
|
||||
}
|
||||
op->setHandlers(mReplyQueue, mSelfHandler, user_handler);
|
||||
op->setReplyPath(mReplyQueue, user_handler);
|
||||
mRequestQueue->addOp(op); // transfers refcount
|
||||
|
||||
mLastReqStatus = status;
|
||||
|
|
@ -220,7 +182,7 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
|
|||
mLastReqStatus = status;
|
||||
return handle;
|
||||
}
|
||||
op->setHandlers(mReplyQueue, mSelfHandler, user_handler);
|
||||
op->setReplyPath(mReplyQueue, user_handler);
|
||||
mRequestQueue->addOp(op); // transfers refcount
|
||||
|
||||
mLastReqStatus = status;
|
||||
|
|
@ -230,19 +192,31 @@ HttpHandle HttpRequest::requestPost(policy_t policy_id,
|
|||
}
|
||||
|
||||
|
||||
HttpHandle HttpRequest::requestCancel(HttpHandle handle, HttpHandler * user_handler)
|
||||
HttpHandle HttpRequest::requestPut(policy_t policy_id,
|
||||
priority_t priority,
|
||||
const std::string & url,
|
||||
BufferArray * body,
|
||||
HttpOptions * options,
|
||||
HttpHeaders * headers,
|
||||
HttpHandler * user_handler)
|
||||
{
|
||||
HttpStatus status;
|
||||
HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID);
|
||||
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
HttpOpCancel * op = new HttpOpCancel(handle);
|
||||
op->setHandlers(mReplyQueue, mSelfHandler, user_handler);
|
||||
mRequestQueue->addOp(op); // transfer refcount as well
|
||||
|
||||
mLastReqStatus = status;
|
||||
ret_handle = static_cast<HttpHandle>(op);
|
||||
HttpOpRequest * op = new HttpOpRequest();
|
||||
if (! (status = op->setupPut(policy_id, priority, url, body, options, headers)))
|
||||
{
|
||||
op->release();
|
||||
mLastReqStatus = status;
|
||||
return handle;
|
||||
}
|
||||
op->setReplyPath(mReplyQueue, user_handler);
|
||||
mRequestQueue->addOp(op); // transfers refcount
|
||||
|
||||
return ret_handle;
|
||||
mLastReqStatus = status;
|
||||
handle = static_cast<HttpHandle>(op);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -252,7 +226,7 @@ HttpHandle HttpRequest::requestNoOp(HttpHandler * user_handler)
|
|||
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
HttpOpNull * op = new HttpOpNull();
|
||||
op->setHandlers(mReplyQueue, mSelfHandler, user_handler);
|
||||
op->setReplyPath(mReplyQueue, user_handler);
|
||||
mRequestQueue->addOp(op); // transfer refcount as well
|
||||
|
||||
mLastReqStatus = status;
|
||||
|
|
@ -262,23 +236,6 @@ HttpHandle HttpRequest::requestNoOp(HttpHandler * user_handler)
|
|||
}
|
||||
|
||||
|
||||
HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority,
|
||||
HttpHandler * handler)
|
||||
{
|
||||
HttpStatus status;
|
||||
HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
HttpOpSetPriority * op = new HttpOpSetPriority(request, priority);
|
||||
op->setHandlers(mReplyQueue, mSelfHandler, handler);
|
||||
mRequestQueue->addOp(op); // transfer refcount as well
|
||||
|
||||
mLastReqStatus = status;
|
||||
ret_handle = static_cast<HttpHandle>(op);
|
||||
|
||||
return ret_handle;
|
||||
}
|
||||
|
||||
|
||||
HttpStatus HttpRequest::update(long millis)
|
||||
{
|
||||
const HttpTime limit(totalTime() + (1000 * HttpTime(millis)));
|
||||
|
|
@ -302,6 +259,38 @@ HttpStatus HttpRequest::update(long millis)
|
|||
// Request Management Methods
|
||||
// ====================================
|
||||
|
||||
HttpHandle HttpRequest::requestCancel(HttpHandle handle, HttpHandler * user_handler)
|
||||
{
|
||||
HttpStatus status;
|
||||
HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
HttpOpCancel * op = new HttpOpCancel(handle);
|
||||
op->setReplyPath(mReplyQueue, user_handler);
|
||||
mRequestQueue->addOp(op); // transfer refcount as well
|
||||
|
||||
mLastReqStatus = status;
|
||||
ret_handle = static_cast<HttpHandle>(op);
|
||||
|
||||
return ret_handle;
|
||||
}
|
||||
|
||||
|
||||
HttpHandle HttpRequest::requestSetPriority(HttpHandle request, priority_t priority,
|
||||
HttpHandler * handler)
|
||||
{
|
||||
HttpStatus status;
|
||||
HttpHandle ret_handle(LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
HttpOpSetPriority * op = new HttpOpSetPriority(request, priority);
|
||||
op->setReplyPath(mReplyQueue, handler);
|
||||
mRequestQueue->addOp(op); // transfer refcount as well
|
||||
|
||||
mLastReqStatus = status;
|
||||
ret_handle = static_cast<HttpHandle>(op);
|
||||
|
||||
return ret_handle;
|
||||
}
|
||||
|
||||
|
||||
// ====================================
|
||||
// Utility Methods
|
||||
|
|
@ -350,7 +339,27 @@ HttpHandle HttpRequest::requestStopThread(HttpHandler * user_handler)
|
|||
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
HttpOpStop * op = new HttpOpStop();
|
||||
op->setHandlers(mReplyQueue, mSelfHandler, user_handler);
|
||||
op->setReplyPath(mReplyQueue, user_handler);
|
||||
mRequestQueue->addOp(op); // transfer refcount as well
|
||||
|
||||
mLastReqStatus = status;
|
||||
handle = static_cast<HttpHandle>(op);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// ====================================
|
||||
// Dynamic Policy Methods
|
||||
// ====================================
|
||||
|
||||
HttpHandle HttpRequest::requestSetHttpProxy(const std::string & proxy, HttpHandler * handler)
|
||||
{
|
||||
HttpStatus status;
|
||||
HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
HttpOpSetGet * op = new HttpOpSetGet();
|
||||
op->setupSet(GP_HTTP_PROXY, proxy);
|
||||
op->setReplyPath(mReplyQueue, handler);
|
||||
mRequestQueue->addOp(op); // transfer refcount as well
|
||||
|
||||
mLastReqStatus = status;
|
||||
|
|
|
|||
|
|
@ -124,8 +124,8 @@ public:
|
|||
/// @param opt Enum of option to be set.
|
||||
/// @param value Desired value of option.
|
||||
/// @return Standard status code.
|
||||
HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, long value);
|
||||
HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, const std::string & value);
|
||||
static HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, long value);
|
||||
static HttpStatus setPolicyGlobalOption(EGlobalPolicy opt, const std::string & value);
|
||||
|
||||
/// Create a new policy class into which requests can be made.
|
||||
///
|
||||
|
|
@ -236,6 +236,32 @@ public:
|
|||
HttpHandler * handler);
|
||||
|
||||
|
||||
///
|
||||
/// @param policy_id Default or user-defined policy class under
|
||||
/// which this request is to be serviced.
|
||||
/// @param priority Standard priority scheme inherited from
|
||||
/// Indra code base.
|
||||
/// @param url
|
||||
/// @param body Byte stream to be sent as the body. No
|
||||
/// further encoding or escaping will be done
|
||||
/// to the content.
|
||||
/// @param options (optional)
|
||||
/// @param headers (optional)
|
||||
/// @param handler (optional)
|
||||
/// @return The handle of the request if successfully
|
||||
/// queued or LLCORE_HTTP_HANDLE_INVALID if the
|
||||
/// request could not be queued. In the latter
|
||||
/// case, @see getStatus() will return more info.
|
||||
///
|
||||
HttpHandle requestPut(policy_t policy_id,
|
||||
priority_t priority,
|
||||
const std::string & url,
|
||||
BufferArray * body,
|
||||
HttpOptions * options,
|
||||
HttpHeaders * headers,
|
||||
HttpHandler * handler);
|
||||
|
||||
|
||||
/// Queue a NoOp request.
|
||||
/// The request is queued and serviced by the working thread which
|
||||
/// immediately processes it and returns the request to the reply
|
||||
|
|
@ -325,13 +351,20 @@ public:
|
|||
HttpHandle requestStopThread(HttpHandler * handler);
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name DynamicPolicyMethods
|
||||
///
|
||||
/// @{
|
||||
|
||||
/// Request that a running transport pick up a new proxy setting.
|
||||
/// An empty string will indicate no proxy is to be used.
|
||||
HttpHandle requestSetHttpProxy(const std::string & proxy, HttpHandler * handler);
|
||||
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
void generateNotification(HttpOperation * op);
|
||||
|
||||
class InternalHandler;
|
||||
friend class InternalHandler;
|
||||
|
||||
private:
|
||||
/// @name InstanceData
|
||||
///
|
||||
|
|
@ -339,7 +372,6 @@ private:
|
|||
HttpStatus mLastReqStatus;
|
||||
HttpReplyQueue * mReplyQueue;
|
||||
HttpRequestQueue * mRequestQueue;
|
||||
InternalHandler * mSelfHandler;
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,8 @@
|
|||
#include "test_bufferarray.hpp"
|
||||
#include "test_httprequestqueue.hpp"
|
||||
|
||||
#include "llproxy.h"
|
||||
|
||||
unsigned long ssl_thread_id_callback(void);
|
||||
void ssl_locking_callback(int mode, int type, const char * file, int line);
|
||||
|
||||
|
|
@ -91,11 +93,15 @@ void init_curl()
|
|||
CRYPTO_set_locking_callback(ssl_locking_callback);
|
||||
CRYPTO_set_id_callback(ssl_thread_id_callback);
|
||||
}
|
||||
|
||||
LLProxy::getInstance();
|
||||
}
|
||||
|
||||
|
||||
void term_curl()
|
||||
{
|
||||
LLProxy::cleanupClass();
|
||||
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
for (int i(0); i < ssl_mutex_count; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -97,13 +97,12 @@ namespace tut
|
|||
|
||||
// Get some handlers
|
||||
TestHandler * h1 = new TestHandler();
|
||||
TestHandler * h2 = new TestHandler();
|
||||
|
||||
// create a new ref counted object with an implicit reference
|
||||
HttpOpNull * op = new HttpOpNull();
|
||||
|
||||
// Add the handlers
|
||||
op->setHandlers(NULL, h1, h2);
|
||||
op->setReplyPath(NULL, h1);
|
||||
|
||||
// Check ref count
|
||||
ensure(op->getRefCount() == 1);
|
||||
|
|
@ -117,8 +116,6 @@ namespace tut
|
|||
// release the handlers
|
||||
delete h1;
|
||||
h1 = NULL;
|
||||
delete h2;
|
||||
h2 = NULL;
|
||||
|
||||
ensure(mMemTotal == GetMemTotal());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#define TEST_LLCORE_HTTP_REQUEST_H_
|
||||
|
||||
#include "httprequest.h"
|
||||
#include "bufferarray.h"
|
||||
#include "httphandler.h"
|
||||
#include "httpresponse.h"
|
||||
#include "_httpservice.h"
|
||||
|
|
@ -604,6 +605,244 @@ void HttpRequestTestObjectType::test<6>()
|
|||
}
|
||||
}
|
||||
|
||||
template <> template <>
|
||||
void HttpRequestTestObjectType::test<7>()
|
||||
{
|
||||
ScopedCurlInit ready;
|
||||
|
||||
std::string url_base(get_base_url());
|
||||
std::cerr << "Base: " << url_base << std::endl;
|
||||
|
||||
set_test_name("HttpRequest PUT to real service");
|
||||
|
||||
// Handler can be stack-allocated *if* there are no dangling
|
||||
// references to it after completion of this method.
|
||||
// Create before memory record as the string copy will bump numbers.
|
||||
TestHandler2 handler(this, "handler");
|
||||
|
||||
// record the total amount of dynamically allocated memory
|
||||
mMemTotal = GetMemTotal();
|
||||
mHandlerCalls = 0;
|
||||
|
||||
HttpRequest * req = NULL;
|
||||
BufferArray * body = new BufferArray;
|
||||
|
||||
try
|
||||
{
|
||||
// Get singletons created
|
||||
HttpRequest::createService();
|
||||
|
||||
// Start threading early so that thread memory is invariant
|
||||
// over the test.
|
||||
HttpRequest::startThread();
|
||||
|
||||
// create a new ref counted object with an implicit reference
|
||||
req = new HttpRequest();
|
||||
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
|
||||
|
||||
// Issue a GET that *can* connect
|
||||
static const char * body_text("Now is the time for all good men...");
|
||||
body->append(body_text, strlen(body_text));
|
||||
mStatus = HttpStatus(200);
|
||||
HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
|
||||
0U,
|
||||
url_base,
|
||||
body,
|
||||
NULL,
|
||||
NULL,
|
||||
&handler);
|
||||
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
// Run the notification pump.
|
||||
int count(0);
|
||||
int limit(10);
|
||||
while (count++ < limit && mHandlerCalls < 1)
|
||||
{
|
||||
req->update(1000);
|
||||
usleep(100000);
|
||||
}
|
||||
ensure("Request executed in reasonable time", count < limit);
|
||||
ensure("One handler invocation for request", mHandlerCalls == 1);
|
||||
|
||||
// Okay, request a shutdown of the servicing thread
|
||||
mStatus = HttpStatus();
|
||||
handle = req->requestStopThread(&handler);
|
||||
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
// Run the notification pump again
|
||||
count = 0;
|
||||
limit = 10;
|
||||
while (count++ < limit && mHandlerCalls < 2)
|
||||
{
|
||||
req->update(1000);
|
||||
usleep(100000);
|
||||
}
|
||||
ensure("Second request executed in reasonable time", count < limit);
|
||||
ensure("Second handler invocation", mHandlerCalls == 2);
|
||||
|
||||
// See that we actually shutdown the thread
|
||||
count = 0;
|
||||
limit = 10;
|
||||
while (count++ < limit && ! HttpService::isStopped())
|
||||
{
|
||||
usleep(100000);
|
||||
}
|
||||
ensure("Thread actually stopped running", HttpService::isStopped());
|
||||
|
||||
// Lose the request body
|
||||
body->release();
|
||||
body = NULL;
|
||||
|
||||
// release the request object
|
||||
delete req;
|
||||
req = NULL;
|
||||
|
||||
// Shut down service
|
||||
HttpRequest::destroyService();
|
||||
|
||||
ensure("Two handler calls on the way out", 2 == mHandlerCalls);
|
||||
|
||||
#if defined(WIN32)
|
||||
// Can only do this memory test on Windows. On other platforms,
|
||||
// the LL logging system holds on to memory and produces what looks
|
||||
// like memory leaks...
|
||||
|
||||
// printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal());
|
||||
ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());
|
||||
#endif
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (body)
|
||||
{
|
||||
body->release();
|
||||
}
|
||||
stop_thread(req);
|
||||
delete req;
|
||||
HttpRequest::destroyService();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
template <> template <>
|
||||
void HttpRequestTestObjectType::test<8>()
|
||||
{
|
||||
ScopedCurlInit ready;
|
||||
|
||||
std::string url_base(get_base_url());
|
||||
std::cerr << "Base: " << url_base << std::endl;
|
||||
|
||||
set_test_name("HttpRequest POST to real service");
|
||||
|
||||
// Handler can be stack-allocated *if* there are no dangling
|
||||
// references to it after completion of this method.
|
||||
// Create before memory record as the string copy will bump numbers.
|
||||
TestHandler2 handler(this, "handler");
|
||||
|
||||
// record the total amount of dynamically allocated memory
|
||||
mMemTotal = GetMemTotal();
|
||||
mHandlerCalls = 0;
|
||||
|
||||
HttpRequest * req = NULL;
|
||||
BufferArray * body = new BufferArray;
|
||||
|
||||
try
|
||||
{
|
||||
// Get singletons created
|
||||
HttpRequest::createService();
|
||||
|
||||
// Start threading early so that thread memory is invariant
|
||||
// over the test.
|
||||
HttpRequest::startThread();
|
||||
|
||||
// create a new ref counted object with an implicit reference
|
||||
req = new HttpRequest();
|
||||
ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
|
||||
|
||||
// Issue a GET that *can* connect
|
||||
static const char * body_text("Now is the time for all good men...");
|
||||
body->append(body_text, strlen(body_text));
|
||||
mStatus = HttpStatus(200);
|
||||
HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
|
||||
0U,
|
||||
url_base,
|
||||
body,
|
||||
NULL,
|
||||
NULL,
|
||||
&handler);
|
||||
ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
// Run the notification pump.
|
||||
int count(0);
|
||||
int limit(10);
|
||||
while (count++ < limit && mHandlerCalls < 1)
|
||||
{
|
||||
req->update(1000);
|
||||
usleep(100000);
|
||||
}
|
||||
ensure("Request executed in reasonable time", count < limit);
|
||||
ensure("One handler invocation for request", mHandlerCalls == 1);
|
||||
|
||||
// Okay, request a shutdown of the servicing thread
|
||||
mStatus = HttpStatus();
|
||||
handle = req->requestStopThread(&handler);
|
||||
ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
|
||||
|
||||
// Run the notification pump again
|
||||
count = 0;
|
||||
limit = 10;
|
||||
while (count++ < limit && mHandlerCalls < 2)
|
||||
{
|
||||
req->update(1000);
|
||||
usleep(100000);
|
||||
}
|
||||
ensure("Second request executed in reasonable time", count < limit);
|
||||
ensure("Second handler invocation", mHandlerCalls == 2);
|
||||
|
||||
// See that we actually shutdown the thread
|
||||
count = 0;
|
||||
limit = 10;
|
||||
while (count++ < limit && ! HttpService::isStopped())
|
||||
{
|
||||
usleep(100000);
|
||||
}
|
||||
ensure("Thread actually stopped running", HttpService::isStopped());
|
||||
|
||||
// Lose the request body
|
||||
body->release();
|
||||
body = NULL;
|
||||
|
||||
// release the request object
|
||||
delete req;
|
||||
req = NULL;
|
||||
|
||||
// Shut down service
|
||||
HttpRequest::destroyService();
|
||||
|
||||
ensure("Two handler calls on the way out", 2 == mHandlerCalls);
|
||||
|
||||
#if defined(WIN32)
|
||||
// Can only do this memory test on Windows. On other platforms,
|
||||
// the LL logging system holds on to memory and produces what looks
|
||||
// like memory leaks...
|
||||
|
||||
// printf("Old mem: %d, New mem: %d\n", mMemTotal, GetMemTotal());
|
||||
ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());
|
||||
#endif
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (body)
|
||||
{
|
||||
body->release();
|
||||
}
|
||||
stop_thread(req);
|
||||
delete req;
|
||||
HttpRequest::destroyService();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace tut
|
||||
|
||||
namespace
|
||||
|
|
|
|||
|
|
@ -85,7 +85,15 @@ class TestHTTPRequestHandler(BaseHTTPRequestHandler):
|
|||
|
||||
def do_POST(self):
|
||||
# Read the provided POST data.
|
||||
self.answer(self.read())
|
||||
# self.answer(self.read())
|
||||
self.answer(dict(reply="success", status=200,
|
||||
reason=self.read()))
|
||||
|
||||
def do_PUT(self):
|
||||
# Read the provided PUT data.
|
||||
# self.answer(self.read())
|
||||
self.answer(dict(reply="success", status=200,
|
||||
reason=self.read()))
|
||||
|
||||
def answer(self, data):
|
||||
debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path)
|
||||
|
|
|
|||
|
|
@ -5358,6 +5358,7 @@ void CoreHttp::init()
|
|||
|
||||
mRequest = new LLCore::HttpRequest;
|
||||
|
||||
// Point to our certs or SSH/https: will fail on connect
|
||||
status = mRequest->setPolicyGlobalOption(LLCore::HttpRequest::GP_CA_FILE,
|
||||
gDirUtilp->getCAFile());
|
||||
if (! status)
|
||||
|
|
@ -5366,6 +5367,18 @@ void CoreHttp::init()
|
|||
<< status.toString()
|
||||
<< LL_ENDL;
|
||||
}
|
||||
|
||||
// Establish HTTP Proxy. "LLProxy" is a special string which directs
|
||||
// the code to use LLProxy::applyProxySettings() to establish any
|
||||
// HTTP or SOCKS proxy for http operations.
|
||||
status = mRequest->setPolicyGlobalOption(LLCore::HttpRequest::GP_HTTP_PROXY,
|
||||
std::string("LLProxy"));
|
||||
if (! status)
|
||||
{
|
||||
LL_ERRS("Init") << "Failed to set HTTP proxy for HTTP services. Reason: "
|
||||
<< status.toString()
|
||||
<< LL_ENDL;
|
||||
}
|
||||
|
||||
status = LLCore::HttpRequest::startThread();
|
||||
if (! status)
|
||||
|
|
|
|||
Loading…
Reference in New Issue