diff --git a/indra/llcorehttp/CMakeLists.txt b/indra/llcorehttp/CMakeLists.txt
index a0827286e35f2ee8262ab6909942464651d7c3fc..4273b32fe34a528cb540e46f3ddbe28fc2a4a56b 100644
--- a/indra/llcorehttp/CMakeLists.txt
+++ b/indra/llcorehttp/CMakeLists.txt
@@ -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}
diff --git a/indra/llcorehttp/_httpopcancel.cpp b/indra/llcorehttp/_httpopcancel.cpp
index 69dbff4bb4726003dfa6675c6abb65b186c06cc8..ad624d2e57154d6189cf7cf26b02ffc27bd44f7d 100644
--- a/indra/llcorehttp/_httpopcancel.cpp
+++ b/indra/llcorehttp/_httpopcancel.cpp
@@ -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
 
 		
diff --git a/indra/llcorehttp/_httpopcancel.h b/indra/llcorehttp/_httpopcancel.h
index fab6f1f3627cafe98276a1dde1a6cd3ac5827eeb..6d1e0f87745e1b4cb71b3f6cacf6c6d6e47ce587 100644
--- a/indra/llcorehttp/_httpopcancel.h
+++ b/indra/llcorehttp/_httpopcancel.h
@@ -59,13 +59,10 @@ class HttpOpCancel : public HttpOperation
 
 public:
 	virtual void stageFromRequest(HttpService *);
-
-	virtual void visitNotifier(HttpRequest * request);
 			
 public:
 	// Request data
 	HttpHandle			mHandle;
-
 };  // end class HttpOpCancel
 
 
diff --git a/indra/llcorehttp/_httpoperation.cpp b/indra/llcorehttp/_httpoperation.cpp
index d966efd12b0202ceec1eaafb4fa0560d5511f0f9..b5c58013d4066114a04c863fcbe49789960e79ad 100644
--- a/indra/llcorehttp/_httpoperation.cpp
+++ b/indra/llcorehttp/_httpoperation.cpp
@@ -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);
diff --git a/indra/llcorehttp/_httpoperation.h b/indra/llcorehttp/_httpoperation.h
index 01e26029d2228d91528f28d6de3493fe7397013b..c93aa2def923c5acfc71528425a3842a4f6f41f1 100644
--- a/indra/llcorehttp/_httpoperation.h
+++ b/indra/llcorehttp/_httpoperation.h
@@ -80,9 +80,8 @@ class HttpOperation : public LLCoreInt::RefCounted
 	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 @@ class HttpOperation : public LLCoreInt::RefCounted
 	
 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
 
 
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index ea0b99303e4f789e8ccd7d0f2959517f92c57a39..e2550d057e0282c285221b126ba24f9074b50fe0 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -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");
diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h
index 6dcf30ca0ccde7409084389eb8f6691c66d63b8a..80893beb40f38b1ed520bedeb4a8cefc00969c25 100644
--- a/indra/llcorehttp/_httpoprequest.h
+++ b/indra/llcorehttp/_httpoprequest.h
@@ -91,6 +91,13 @@ class HttpOpRequest : public HttpOperation
 						 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();
diff --git a/indra/llcorehttp/_httpopsetget.cpp b/indra/llcorehttp/_httpopsetget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..21e058b2be56b3aed1e8083f994f53e4bf73567e
--- /dev/null
+++ b/indra/llcorehttp/_httpopsetget.cpp
@@ -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
+
+		
diff --git a/indra/llcorehttp/_httpopsetget.h b/indra/llcorehttp/_httpopsetget.h
new file mode 100644
index 0000000000000000000000000000000000000000..e065eb4c30c3f37b1915f93ea8f75b2ca1312e37
--- /dev/null
+++ b/indra/llcorehttp/_httpopsetget.h
@@ -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_
+
diff --git a/indra/llcorehttp/_httpopsetpriority.cpp b/indra/llcorehttp/_httpopsetpriority.cpp
index b0ee577087b1c6d90dd3de73754caecf3329fd12..d48c7a0b7d63bc58f43a3ab34fd669ec2f05eae2 100644
--- a/indra/llcorehttp/_httpopsetpriority.cpp
+++ b/indra/llcorehttp/_httpopsetpriority.cpp
@@ -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
diff --git a/indra/llcorehttp/_httpopsetpriority.h b/indra/llcorehttp/_httpopsetpriority.h
index b972f50fff0a8042d27f5af8bcb33aca315c9d76..f1e94b6e4312b0d00a083ecfb5e90eed41c1364c 100644
--- a/indra/llcorehttp/_httpopsetpriority.h
+++ b/indra/llcorehttp/_httpopsetpriority.h
@@ -56,10 +56,8 @@ class HttpOpSetPriority : public HttpOperation
 public:
 	virtual void stageFromRequest(HttpService *);
 
-	virtual void visitNotifier(HttpRequest * request);
-
 protected:
-	HttpStatus					mStatus;
+	// Request Data
 	HttpHandle					mHandle;
 	HttpRequest::priority_t		mPriority;
 }; // end class HttpOpSetPriority
diff --git a/indra/llcorehttp/_httppolicy.cpp b/indra/llcorehttp/_httppolicy.cpp
index 72bb6f14e43a9b4116f5d7362f5097e1615360d8..8ee3f886583f48bb1ca8e51d3b2e96aea0c6c912 100644
--- a/indra/llcorehttp/_httppolicy.cpp
+++ b/indra/llcorehttp/_httppolicy.cpp
@@ -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);
diff --git a/indra/llcorehttp/_httppolicy.h b/indra/llcorehttp/_httppolicy.h
index 14f6a9a6760a53ec398457e42c9d8a41d33ca085..73c22bab789af26830b4ef4e889034ff0c30242d 100644
--- a/indra/llcorehttp/_httppolicy.h
+++ b/indra/llcorehttp/_httppolicy.h
@@ -95,7 +95,9 @@ class HttpPolicy
 		{
 			return mGlobalOptions;
 		}
-	
+
+	void setPolicies(const HttpPolicyGlobal & global);
+			
 protected:
 	struct State
 	{
diff --git a/indra/llcorehttp/_httppolicyglobal.cpp b/indra/llcorehttp/_httppolicyglobal.cpp
index 877b85896fb6952c9d35796c1c76968d09c1b6bf..d95d73cfba0d717c57d9563d1251f55565501547 100644
--- a/indra/llcorehttp/_httppolicyglobal.cpp
+++ b/indra/llcorehttp/_httppolicyglobal.cpp
@@ -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:
diff --git a/indra/llcorehttp/_httppolicyglobal.h b/indra/llcorehttp/_httppolicyglobal.h
index 39ffbcb9bbace7aa9856d16815c78fb171edcc18..f4bb4d4b258dc4841d05bb08d3f4bf7ecf956b5e 100644
--- a/indra/llcorehttp/_httppolicyglobal.h
+++ b/indra/llcorehttp/_httppolicyglobal.h
@@ -40,18 +40,19 @@ class HttpPolicyGlobal
 	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;
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index b038bdb720930d3ab5245a7861a7b8cfdc1762aa..920a3f3b6d029ab41eef8165f872b86e5dcf99b0 100644
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -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;
diff --git a/indra/llcorehttp/_httpservice.h b/indra/llcorehttp/_httpservice.h
index 748354a8e4923541454b8dea0236db8d07b291a5..3f953ec1a7f7b4bc7a94714d73de87444eca6bb2 100644
--- a/indra/llcorehttp/_httpservice.h
+++ b/indra/llcorehttp/_httpservice.h
@@ -30,6 +30,7 @@
 
 #include "httpcommon.h"
 #include "httprequest.h"
+#include "_httppolicyglobal.h"
 
 
 namespace LLCoreInt
@@ -157,6 +158,11 @@ class HttpService
 		{
 			return *mTransport;
 		}
+
+	HttpPolicyGlobal & getGlobalOptions()
+		{
+			return mPolicyGlobal;
+		}
 	
 protected:
 	void threadRun(LLCoreInt::HttpThread * thread);
@@ -173,11 +179,11 @@ class HttpService
 	
 	// === 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
diff --git a/indra/llcorehttp/httprequest.cpp b/indra/llcorehttp/httprequest.cpp
index 2f36168f8b84f1b48baf79b12e8d5653354875a2..089eee76f3315a79ee628a6ebd9b48ae3f96b302 100644
--- a/indra/llcorehttp/httprequest.cpp
+++ b/indra/llcorehttp/httprequest.cpp
@@ -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);
-
-	HttpOpCancel * op = new HttpOpCancel(handle);
-	op->setHandlers(mReplyQueue, mSelfHandler, user_handler);
-	mRequestQueue->addOp(op);			// transfer refcount as well
+	HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID);
 
+	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
+	
 	mLastReqStatus = status;
-	ret_handle = static_cast<HttpHandle>(op);
+	handle = static_cast<HttpHandle>(op);
 	
-	return ret_handle;
+	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;
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index 01dbfba6dd0226f8b6b1f68ab727c9ab419ac2a8..a953aa28d0a799c6f84d539477db113b337cf010 100644
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -124,8 +124,8 @@ class HttpRequest
 	/// @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 @@ class HttpRequest
 						   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 @@ class HttpRequest
 	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 @@ class HttpRequest
 	HttpStatus			mLastReqStatus;
 	HttpReplyQueue *	mReplyQueue;
 	HttpRequestQueue *	mRequestQueue;
-	InternalHandler *	mSelfHandler;
 	
 	/// @}
 	
diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp
index f59361ab53f59c40d5480e8c49253fb9363b7019..2b36d3a982cdade5da0a64607bcf3a1909fb7bd7 100644
--- a/indra/llcorehttp/tests/llcorehttp_test.cpp
+++ b/indra/llcorehttp/tests/llcorehttp_test.cpp
@@ -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)
 	{
diff --git a/indra/llcorehttp/tests/test_httpoperation.hpp b/indra/llcorehttp/tests/test_httpoperation.hpp
index 6c3df1e9e38f85e82e9f24d059f9fcb4f69c855f..17b1a96878325e8240648d1f904cd65bf461cda7 100644
--- a/indra/llcorehttp/tests/test_httpoperation.hpp
+++ b/indra/llcorehttp/tests/test_httpoperation.hpp
@@ -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());
 	}
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index 81f8fe4a850e22ae5ae17753c5ecfef510f9625d..61698f34d84c89754f0de50d126bee0ac1530325 100644
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -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
diff --git a/indra/llcorehttp/tests/test_llcorehttp_peer.py b/indra/llcorehttp/tests/test_llcorehttp_peer.py
index 3e200a5c1965a640a6e6c5490b5b5f250034f3e0..8c3ad805b3e3c1fbe90249d1bdfbbc01317e6d6b 100644
--- a/indra/llcorehttp/tests/test_llcorehttp_peer.py
+++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py
@@ -85,7 +85,15 @@ def do_GET(self):
 
     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)
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 7a44415fba9bd82a042b4893698e635de33d5aa9..e2c13e77e3a4f2cbfd1922f2940c4d1a545034a1 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -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)