diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index b1b05dc285f9a240105672b6e5c7fee07f5c526f..3b6647882e11b0f4a6242af26c6e807501384373 100755
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -532,6 +532,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 	long sslPeerV(0L);
 	long sslHostV(0L);
     long dnsCacheTimeout(-1L);
+    long nobody(0L);
 
 	if (mReqOptions)
 	{
@@ -539,6 +540,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 		sslPeerV = mReqOptions->getSSLVerifyPeer() ? 1L : 0L;
 		sslHostV = mReqOptions->getSSLVerifyHost() ? 2L : 0L;
 		dnsCacheTimeout = mReqOptions->getDNSCacheTimeout();
+        nobody = mReqOptions->getHeadersOnly() ? 1L : 0L;
 	}
 	code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect);
 	check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION);
@@ -548,6 +550,9 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 	code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, sslHostV);
 	check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST);
 
+    code = curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody);
+    check_curl_easy_code(code, CURLOPT_NOBODY);
+
 	// The Linksys WRT54G V5 router has an issue with frequent
 	// DNS lookups from LAN machines.  If they happen too often,
 	// like for every HTTP request, the router gets annoyed after
@@ -587,7 +592,8 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
 	switch (mReqMethod)
 	{
 	case HOR_GET:
-		code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
+        if (nobody == 0)
+            code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
 		check_curl_easy_code(code, CURLOPT_HTTPGET);
 		break;
 		
diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index a4d08a80dfadfb507c47a5ad44a1f824085a02be..2b42bcaf6dafebaa00ad41fec7275ca8466515ed 100755
--- a/indra/llcorehttp/httpoptions.cpp
+++ b/indra/llcorehttp/httpoptions.cpp
@@ -34,16 +34,17 @@ namespace LLCore
 
 
 HttpOptions::HttpOptions() : RefCounted(true),
-	mWantHeaders(false),
-	mTracing(HTTP_TRACE_OFF),
-	mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT),
-	mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT),
-	mRetries(HTTP_RETRY_COUNT_DEFAULT),
-	mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT),
-	mFollowRedirects(false),
-	mVerifyPeer(false),
-	mVerifyHost(false),
-    mDNSCacheTimeout(-1L)
+    mWantHeaders(false),
+    mTracing(HTTP_TRACE_OFF),
+    mTimeout(HTTP_REQUEST_TIMEOUT_DEFAULT),
+    mTransferTimeout(HTTP_REQUEST_XFER_TIMEOUT_DEFAULT),
+    mRetries(HTTP_RETRY_COUNT_DEFAULT),
+    mUseRetryAfter(HTTP_USE_RETRY_AFTER_DEFAULT),
+    mFollowRedirects(false),
+    mVerifyPeer(false),
+    mVerifyHost(false),
+    mDNSCacheTimeout(-1L),
+    mNoBody(false)
 {}
 
 
@@ -104,4 +105,12 @@ void HttpOptions::setDNSCacheTimeout(int timeout)
 {
 	mDNSCacheTimeout = timeout;
 }
+
+void HttpOptions::setHeadersOnly(bool nobody)
+{
+    mNoBody = nobody;
+    if (mNoBody)
+        setWantHeaders(true);
+}
+
 }   // end namespace LLCore
diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h
index 765d2431bbf7b9028c3451f8a551ffe47c087928..21ecff85af2c73e4e662e8b2b3631c12d39899a3 100755
--- a/indra/llcorehttp/httpoptions.h
+++ b/indra/llcorehttp/httpoptions.h
@@ -149,6 +149,15 @@ class HttpOptions : public LLCoreInt::RefCounted
 	{
 		return mDNSCacheTimeout;
 	}
+
+    /// Retrieve only the headers and status from the request. Setting this 
+    /// to true implies setWantHeaders(true) as well.
+    /// Default: false
+    void                setHeadersOnly(bool nobody);
+    bool                getHeadersOnly() const
+    {
+        return mNoBody;
+    }
 	
 protected:
 	bool				mWantHeaders;
@@ -161,6 +170,7 @@ class HttpOptions : public LLCoreInt::RefCounted
 	bool				mVerifyPeer;
 	bool        		mVerifyHost;
 	int					mDNSCacheTimeout;
+    bool                mNoBody;
 }; // end class HttpOptions
 
 
diff --git a/indra/llmessage/llcorehttputil.cpp b/indra/llmessage/llcorehttputil.cpp
index 001df9e3850091e68b26c00dfc90fd2f5a4dad20..c4a7e9040a782a0cb962a6f81bf850b4ece0bbd8 100644
--- a/indra/llmessage/llcorehttputil.cpp
+++ b/indra/llmessage/llcorehttputil.cpp
@@ -256,7 +256,7 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
 
     buildStatusEntry(response, status, result);
 
-#if 0
+#if 1
     // commenting out, but keeping since this can be useful for debugging
     if (!status)
     {
@@ -608,6 +608,16 @@ LLSD HttpCoroutineAdapter::postAndYield(LLCoros::self & self, LLCore::HttpReques
     return postAndYield_(self, request, url, rawbody, options, headers, httpHandler);
 }
 
+LLSD HttpCoroutineAdapter::postRawAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request,
+    const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+    LLCore::HttpOptions::ptr_t options, LLCore::HttpHeaders::ptr_t headers)
+{
+    LLEventStream  replyPump(mAdapterName, true);
+    HttpCoroHandler::ptr_t httpHandler = HttpCoroHandler::ptr_t(new HttpCoroRawHandler(replyPump));
+
+    return postAndYield_(self, request, url, rawbody, options, headers, httpHandler);
+}
+
 LLSD HttpCoroutineAdapter::postAndYield_(LLCoros::self & self, LLCore::HttpRequest::ptr_t &request,
     const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
     LLCore::HttpOptions::ptr_t &options, LLCore::HttpHeaders::ptr_t &headers,
diff --git a/indra/llmessage/llcorehttputil.h b/indra/llmessage/llcorehttputil.h
index d6219318f9e3faa0b3304315b2383ee4a1ea9969..213610e58e114e165d328fb72b1941231c60c99b 100644
--- a/indra/llmessage/llcorehttputil.h
+++ b/indra/llmessage/llcorehttputil.h
@@ -334,6 +334,19 @@ class HttpCoroutineAdapter
             LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), headers);
     }
 
+    LLSD postRawAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t request,
+        const std::string & url, LLCore::BufferArray::ptr_t rawbody,
+        LLCore::HttpOptions::ptr_t options = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false),
+        LLCore::HttpHeaders::ptr_t headers = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false));
+
+    LLSD postRawAndYield(LLCoros::self & self, LLCore::HttpRequest::ptr_t &request,
+        const std::string & url, LLCore::BufferArray::ptr_t &rawbody,
+        LLCore::HttpHeaders::ptr_t &headers)
+    {
+        return postRawAndYield(self, request, url, rawbody,
+            LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false), headers);
+    }
+
     /// Execute a Put transaction on the supplied URL and yield execution of 
     /// the coroutine until a result is available.
     /// 
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 509227c6835f9f99be7cc7e9de3092df46440003..02167b099e4277be7bbd207fad52aa25d264b265 100755
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -69,6 +69,7 @@
 #include "llwebprofile.h"
 #include "llwindow.h"
 #include "llvieweraudio.h"
+#include "llcorehttputil.h"
 
 #include "llfloaterwebcontent.h"	// for handling window close requests and geometry change requests in media browser windows.
 
@@ -152,190 +153,6 @@ LLViewerMediaObserver::~LLViewerMediaObserver()
 }
 
 
-// Move this to its own file.
-// helper class that tries to download a URL from a web site and calls a method
-// on the Panel Land Media and to discover the MIME type
-class LLMimeDiscoveryResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLMimeDiscoveryResponder);
-public:
-	LLMimeDiscoveryResponder( viewer_media_t media_impl)
-		: mMediaImpl(media_impl),
-		  mInitialized(false)
-	{
-		if(mMediaImpl->mMimeTypeProbe != NULL)
-		{
-			LL_ERRS() << "impl already has an outstanding responder" << LL_ENDL;
-		}
-		
-		mMediaImpl->mMimeTypeProbe = this;
-	}
-
-	~LLMimeDiscoveryResponder()
-	{
-		disconnectOwner();
-	}
-
-private:
-	/* virtual */ void httpCompleted()
-	{
-		if (!isGoodStatus())
-		{
-			LL_WARNS() << dumpResponse()
-					<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
-		}
-		const std::string& media_type = getResponseHeader(HTTP_IN_HEADER_CONTENT_TYPE);
-		std::string::size_type idx1 = media_type.find_first_of(";");
-		std::string mime_type = media_type.substr(0, idx1);
-
-		LL_DEBUGS() << "status is " << getStatus() << ", media type \"" << media_type << "\"" << LL_ENDL;
-		
-		// 2xx status codes indicate success.
-		// Most 4xx status codes are successful enough for our purposes.
-		// 499 is the error code for host not found, timeout, etc.
-		// 500 means "Internal Server error" but we decided it's okay to 
-		//     accept this and go past it in the MIME type probe
-		// 302 means the resource can be found temporarily in a different place - added this for join.secondlife.com
-		// 499 is a code specifc to join.secondlife.com (?) apparently safe to ignore
-//		if(	((status >= 200) && (status < 300))	||
-//			((status >= 400) && (status < 499))	|| 
-//			(status == 500) ||
-//			(status == 302) ||
-//			(status == 499) 
-//			)
-		// We now no longer check the error code returned from the probe.
-		// If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting.
-		//if(1)
-		{
-			// The probe was successful.
-			if(mime_type.empty())
-			{
-				// Some sites don't return any content-type header at all.
-				// Treat an empty mime type as text/html.
-				mime_type = HTTP_CONTENT_TEXT_HTML;
-			}
-		}
-		//else
-		//{
-		//	LL_WARNS() << "responder failed with status " << dumpResponse() << LL_ENDL;
-		//
-		//	if(mMediaImpl)
-		//	{
-		//		mMediaImpl->mMediaSourceFailed = true;
-		//	}
-		//	return;
-		//}
-
-		// the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
-		// Make a local copy so we can call loadURI() afterwards.
-		LLViewerMediaImpl *impl = mMediaImpl;
-		
-		if(impl && !mInitialized && ! mime_type.empty())
-		{
-			if(impl->initializeMedia(mime_type))
-			{
-				mInitialized = true;
-				impl->loadURI();
-				disconnectOwner();
-			}
-		}
-	}
-	
-public:
-	void cancelRequest()
-	{
-		disconnectOwner();
-	}
-	
-private:
-	void disconnectOwner()
-	{
-		if(mMediaImpl)
-		{
-			if(mMediaImpl->mMimeTypeProbe != this)
-			{
-				LL_ERRS() << "internal error: mMediaImpl->mMimeTypeProbe != this" << LL_ENDL;
-			}
-
-			mMediaImpl->mMimeTypeProbe = NULL;
-		}
-		mMediaImpl = NULL;
-	}
-	
-	
-public:
-		LLViewerMediaImpl *mMediaImpl;
-		bool mInitialized;
-};
-
-class LLViewerMediaOpenIDResponder : public LLHTTPClient::Responder
-{
-	LOG_CLASS(LLViewerMediaOpenIDResponder);
-public:
-	LLViewerMediaOpenIDResponder( )
-	{
-	}
-
-	~LLViewerMediaOpenIDResponder()
-	{
-	}
-
-	/* virtual */ void completedRaw(
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// We don't care about the content of the response, only the Set-Cookie header.
-		LL_DEBUGS("MediaAuth") << dumpResponse() 
-				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
-		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
-		
-		// *TODO: What about bad status codes?  Does this destroy previous cookies?
-		LLViewerMedia::openIDCookieResponse(cookie);
-	}
-
-};
-
-class LLViewerMediaWebProfileResponder : public LLHTTPClient::Responder
-{
-LOG_CLASS(LLViewerMediaWebProfileResponder);
-public:
-	LLViewerMediaWebProfileResponder(std::string host)
-	{
-		mHost = host;
-	}
-
-	~LLViewerMediaWebProfileResponder()
-	{
-	}
-
-	 void completedRaw(
-		const LLChannelDescriptors& channels,
-		const LLIOPipe::buffer_ptr_t& buffer)
-	{
-		// We don't care about the content of the response, only the set-cookie header.
-		LL_WARNS("MediaAuth") << dumpResponse() 
-				<< " [headers:" << getResponseHeaders() << "]" << LL_ENDL;
-
-		LLSD stripped_content = getResponseHeaders();
-		// *TODO: Check that this works.
-		stripped_content.erase(HTTP_IN_HEADER_SET_COOKIE);
-		LL_WARNS("MediaAuth") << stripped_content << LL_ENDL;
-
-		const std::string& cookie = getResponseHeader(HTTP_IN_HEADER_SET_COOKIE);
-		LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL;
-
-		// *TODO: What about bad status codes?  Does this destroy previous cookies?
-		LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, mHost);
-
-		// Set cookie for snapshot publishing.
-		std::string auth_cookie = cookie.substr(0, cookie.find(";")); // strip path
-		LLWebProfile::setAuthCookie(auth_cookie);
-	}
-
-	std::string mHost;
-};
-
-
 LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL;
 LLURL LLViewerMedia::sOpenIDURL;
 std::string LLViewerMedia::sOpenIDCookie;
@@ -1394,81 +1211,154 @@ void LLViewerMedia::setOpenIDCookie()
 {
 	if(!sOpenIDCookie.empty())
 	{
-		// The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port]
-		// We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that.
-		// We therefore do it here.
-		std::string authority = sOpenIDURL.mAuthority;
-		std::string::size_type host_start = authority.find('@'); 
-		if(host_start == std::string::npos)
-		{
-			// no username/password
-			host_start = 0;
-		}
-		else
-		{
-			// Hostname starts after the @. 
-			// (If the hostname part is empty, this may put host_start at the end of the string.  In that case, it will end up passing through an empty hostname, which is correct.)
-			++host_start;
-		}
-		std::string::size_type host_end = authority.rfind(':'); 
-		if((host_end == std::string::npos) || (host_end < host_start))
-		{
-			// no port
-			host_end = authority.size();
-		}
-		
-		getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(host_start, host_end - host_start));
+        std::string profileUrl = getProfileURL("");
+
+        LLCoros::instance().launch("LLViewerMedia::getOpenIDCookieCoro",
+            boost::bind(&LLViewerMedia::getOpenIDCookieCoro, _1, profileUrl));
+	}
+}
 
-		// Do a web profile get so we can store the cookie 
-		LLSD headers = LLSD::emptyMap();
-		headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
-		headers[HTTP_OUT_HEADER_COOKIE] = sOpenIDCookie;
-		headers[HTTP_OUT_HEADER_USER_AGENT] = getCurrentUserAgent();
+/*static*/
+void LLViewerMedia::getOpenIDCookieCoro(LLCoros::self& self, std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("getOpenIDCookieCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+    
+    httpOpts->setFollowRedirects(true);
+    httpOpts->setWantHeaders(true);
+
+    LLURL hostUrl(url.c_str());
+    std::string hostAuth = hostUrl.getAuthority();
+
+    // *TODO: Expand LLURL to split and extract this information better. 
+    // The structure of a URL is well defined and needing to retrieve parts of it are common.
+    // original comment:
+    // The LLURL can give me the 'authority', which is of the form: [username[:password]@]hostname[:port]
+    // We want just the hostname for the cookie code, but LLURL doesn't seem to have a way to extract that.
+    // We therefore do it here.
+    std::string authority = sOpenIDURL.mAuthority;
+    std::string::size_type hostStart = authority.find('@');
+    if (hostStart == std::string::npos)
+    {   // no username/password
+        hostStart = 0;
+    }
+    else
+    {   // Hostname starts after the @. 
+        // (If the hostname part is empty, this may put host_start at the end of the string.  In that case, it will end up passing through an empty hostname, which is correct.)
+        ++hostStart;
+    }
+    std::string::size_type hostEnd = authority.rfind(':');
+    if ((hostEnd == std::string::npos) || (hostEnd < hostStart))
+    {   // no port
+        hostEnd = authority.size();
+    }
 
-		std::string profile_url = getProfileURL("");
-		LLURL raw_profile_url( profile_url.c_str() );
+    getCookieStore()->setCookiesFromHost(sOpenIDCookie, authority.substr(hostStart, hostEnd - hostStart));
+
+    // Do a web profile get so we can store the cookie 
+    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, sOpenIDCookie);
+    httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, getCurrentUserAgent());
+
+
+    LL_DEBUGS("MediaAuth") << "Requesting " << url << LL_ENDL;
+    LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL;
+    
+    LLSD result = httpAdapter->getRawAndYield(self, httpRequest, url, httpOpts, httpHeaders);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("MediaAuth") << "Error getting web profile." << LL_ENDL;
+        return;
+    }
+
+    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+    if (!resultHeaders.has(HTTP_IN_HEADER_SET_COOKIE))
+    {
+        LL_WARNS("MediaAuth") << "No cookie in response." << LL_ENDL;
+        return;
+    }
+
+    const std::string& cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE].asStringRef();
+    LL_DEBUGS("MediaAuth") << "cookie = " << cookie << LL_ENDL;
+
+    // *TODO: What about bad status codes?  Does this destroy previous cookies?
+    LLViewerMedia::getCookieStore()->setCookiesFromHost(cookie, hostAuth);
+
+    // Set cookie for snapshot publishing.
+    std::string authCookie = cookie.substr(0, cookie.find(";")); // strip path
+    LLWebProfile::setAuthCookie(authCookie);
 
-		LL_DEBUGS("MediaAuth") << "Requesting " << profile_url << LL_ENDL;
-		LL_DEBUGS("MediaAuth") << "sOpenIDCookie = [" << sOpenIDCookie << "]" << LL_ENDL;
-		LLHTTPClient::get(profile_url,  
-			new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()),
-			headers);
-	}
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
 // static
-void LLViewerMedia::openIDSetup(const std::string &openid_url, const std::string &openid_token)
+void LLViewerMedia::openIDSetup(const std::string &openidUrl, const std::string &openidToken)
 {
-	LL_DEBUGS("MediaAuth") << "url = \"" << openid_url << "\", token = \"" << openid_token << "\"" << LL_ENDL;
+	LL_DEBUGS("MediaAuth") << "url = \"" << openidUrl << "\", token = \"" << openidToken << "\"" << LL_ENDL;
 
-	// post the token to the url 
-	// the responder will need to extract the cookie(s).
+    LLCoros::instance().launch("LLViewerMedia::openIDSetupCoro",
+        boost::bind(&LLViewerMedia::openIDSetupCoro, _1, openidUrl, openidToken));
+}
 
-	// Save the OpenID URL for later -- we may need the host when adding the cookie.
-	sOpenIDURL.init(openid_url.c_str());
-	
-	// We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
-	sOpenIDCookie.clear();
+/*static*/
+void LLViewerMedia::openIDSetupCoro(LLCoros::self& self, std::string openidUrl, std::string openidToken)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("openIDSetupCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
 
-	LLSD headers = LLSD::emptyMap();
-	// Keep LLHTTPClient from adding an "Accept: application/llsd+xml" header
-	headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
-	// and use the expected content-type for a post, instead of the LLHTTPClient::postRaw() default of "application/octet-stream"
-	headers[HTTP_OUT_HEADER_CONTENT_TYPE] = "application/x-www-form-urlencoded";
-
-	// postRaw() takes ownership of the buffer and releases it later, so we need to allocate a new buffer here.
-	size_t size = openid_token.size();
-	U8 *data = new U8[size];
-	memcpy(data, openid_token.data(), size);
-
-	LLHTTPClient::postRaw( 
-		openid_url, 
-		data, 
-		size, 
-		new LLViewerMediaOpenIDResponder(),
-		headers);
-			
+    httpOpts->setWantHeaders(true);
+
+    // post the token to the url 
+    // the responder will need to extract the cookie(s).
+    // Save the OpenID URL for later -- we may need the host when adding the cookie.
+    sOpenIDURL.init(openidUrl.c_str());
+    // We shouldn't ever do this twice, but just in case this code gets repurposed later, clear existing cookies.
+    sOpenIDCookie.clear();
+
+    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+    httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/x-www-form-urlencoded");
+
+    LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray, false);
+    LLCore::BufferArrayStream bas(rawbody.get());
+
+    bas << std::noskipws << openidToken;
+
+    LLSD result = httpAdapter->postRawAndYield(self, httpRequest, openidUrl, rawbody, httpOpts, httpHeaders);
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS("MediaAuth") << "Error getting Open ID cookie" << LL_ENDL;
+        return;
+    }
+
+    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+    if (!resultHeaders.has(HTTP_IN_HEADER_SET_COOKIE))
+    {
+        LL_WARNS("MediaAuth") << "No cookie in response." << LL_ENDL;
+        return;
+    }
+
+    // We don't care about the content of the response, only the Set-Cookie header.
+    const std::string &cookie = resultHeaders[HTTP_IN_HEADER_SET_COOKIE];
+
+    // *TODO: What about bad status codes?  Does this destroy previous cookies?
+    LLViewerMedia::openIDCookieResponse(cookie);
+    LL_DEBUGS("MediaAuth") << "OpenID cookie set." << LL_ENDL;
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
@@ -1661,7 +1551,6 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	mIsParcelMedia(false),
 	mProximity(-1),
 	mProximityDistance(0.0f),
-	mMimeTypeProbe(NULL),
 	mMediaAutoPlay(false),
 	mInNearbyMediaList(false),
 	mClearCache(false),
@@ -1671,8 +1560,10 @@ LLViewerMediaImpl::LLViewerMediaImpl(	  const LLUUID& texture_id,
 	mIsUpdated(false),
 	mTrustedBrowser(false),
 	mZoomFactor(1.0),
-    mCleanBrowser(false)
-{ 
+    mCleanBrowser(false),
+    mMimeProbe(),
+    mCanceling(false)
+{
 
 	// Set up the mute list observer if it hasn't been set up already.
 	if(!sViewerMediaMuteListObserverInitialized)
@@ -2610,7 +2501,8 @@ void LLViewerMediaImpl::navigateInternal()
 		return;
 	}
 	
-	if(mMimeTypeProbe != NULL)
+    
+    if (!mMimeProbe.expired())
 	{
 		LL_WARNS() << "MIME type probe already in progress -- bailing out." << LL_ENDL;
 		return;
@@ -2648,14 +2540,8 @@ void LLViewerMediaImpl::navigateInternal()
 
 		if(scheme.empty() || "http" == scheme || "https" == scheme)
 		{
-			// If we don't set an Accept header, LLHTTPClient will add one like this:
-			//    Accept: application/llsd+xml
-			// which is really not what we want.
-			LLSD headers = LLSD::emptyMap();
-			headers[HTTP_OUT_HEADER_ACCEPT] = "*/*";
-			// Allow cookies in the response, to prevent a redirect loop when accessing join.secondlife.com
-			headers[HTTP_OUT_HEADER_COOKIE] = "";
-			LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), headers, 10.0f);
+            LLCoros::instance().launch("LLViewerMediaImpl::mimeDiscoveryCoro",
+                boost::bind(&LLViewerMediaImpl::mimeDiscoveryCoro, this, _1, mMediaURL));
 		}
 		else if("data" == scheme || "file" == scheme || "about" == scheme)
 		{
@@ -2685,6 +2571,65 @@ void LLViewerMediaImpl::navigateInternal()
 	}
 }
 
+void LLViewerMediaImpl::mimeDiscoveryCoro(LLCoros::self& self, std::string url)
+{
+    LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
+        httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("mimeDiscoveryCoro", httpPolicy));
+    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
+    LLCore::HttpOptions::ptr_t httpOpts(new LLCore::HttpOptions);
+    LLCore::HttpHeaders::ptr_t httpHeaders(new LLCore::HttpHeaders);
+
+    mMimeProbe = httpAdapter;
+
+    httpOpts->setHeadersOnly(true);
+
+    httpHeaders->append(HTTP_OUT_HEADER_ACCEPT, "*/*");
+    httpHeaders->append(HTTP_OUT_HEADER_COOKIE, "");
+
+    LLSD result = httpAdapter->getRawAndYield(self, httpRequest, url, httpOpts, httpHeaders);
+
+    mMimeProbe.reset();
+
+    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+    if (!status)
+    {
+        LL_WARNS() << "Error retrieving media headers." << LL_ENDL;
+    }
+
+    LLSD resultHeaders = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS];
+    
+    const std::string& mediaType = resultHeaders[HTTP_IN_HEADER_CONTENT_TYPE].asStringRef();
+
+    std::string::size_type idx1 = mediaType.find_first_of(";");
+    std::string mimeType = mediaType.substr(0, idx1);
+
+    // We now no longer need to check the error code returned from the probe.
+    // If we have a mime type, use it.  If not, default to the web plugin and let it handle error reporting.
+    // The probe was successful.
+    if (mimeType.empty())
+    {
+        // Some sites don't return any content-type header at all.
+        // Treat an empty mime type as text/html.
+        mimeType = HTTP_CONTENT_TEXT_HTML;
+    }
+
+    LL_DEBUGS() << "Media type \"" << mediaType << "\", mime type is \"" << mimeType << "\"" << LL_ENDL;
+
+    // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
+    // Make a local copy so we can call loadURI() afterwards.
+
+    if (!mimeType.empty())
+    {
+        if (initializeMedia(mimeType))
+        {
+            loadURI();
+        }
+    }
+}
+
 //////////////////////////////////////////////////////////////////////////////////////////
 void LLViewerMediaImpl::navigateStop()
 {
@@ -2783,7 +2728,7 @@ void LLViewerMediaImpl::update()
 		{
 			// Don't load new instances that are at PRIORITY_SLIDESHOW or below.  They're just kept around to preserve state.
 		}
-		else if(mMimeTypeProbe != NULL)
+        else if (!mMimeProbe.expired())
 		{
 			// this media source is doing a MIME type probe -- don't try loading it again.
 		}
@@ -3673,18 +3618,10 @@ void LLViewerMediaImpl::setNavigateSuspended(bool suspend)
 
 void LLViewerMediaImpl::cancelMimeTypeProbe()
 {
-	if(mMimeTypeProbe != NULL)
-	{
-		// There doesn't seem to be a way to actually cancel an outstanding request.
-		// Simulate it by telling the LLMimeDiscoveryResponder not to write back any results.
-		mMimeTypeProbe->cancelRequest();
-		
-		// The above should already have set mMimeTypeProbe to NULL.
-		if(mMimeTypeProbe != NULL)
-		{
-			LL_ERRS() << "internal error: mMimeTypeProbe is not NULL after cancelling request." << LL_ENDL;
-		}
-	}
+    LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t probeAdapter = mMimeProbe.lock();
+
+    if (probeAdapter)
+        probeAdapter->cancelYieldingOperation();
 }
 
 void LLViewerMediaImpl::addObject(LLVOVolume* obj) 
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 6803adfaa251bc986ff6a76aacebc9009f1f5e70..5658651c6e86a9891bbcd18ac284c045cbb20c4f 100755
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -40,6 +40,9 @@
 #include "llnotificationptr.h"
 
 #include "llurl.h"
+#include "lleventcoro.h"
+#include "llcoros.h"
+#include "llcorehttputil.h"
 
 class LLViewerMediaImpl;
 class LLUUID;
@@ -165,7 +168,10 @@ class LLViewerMedia
 private:
 	static void setOpenIDCookie();
 	static void onTeleportFinished();
-	
+
+    static void openIDSetupCoro(LLCoros::self& self, std::string openidUrl, std::string openidToken);
+    static void getOpenIDCookieCoro(LLCoros::self& self, std::string url);
+
 	static LLPluginCookieStore *sCookieStore;
 	static LLURL sOpenIDURL;
 	static std::string sOpenIDCookie;
@@ -180,7 +186,6 @@ class LLViewerMediaImpl
 public:
 	
 	friend class LLViewerMedia;
-	friend class LLMimeDiscoveryResponder;
 	
 	LLViewerMediaImpl(
 		const LLUUID& texture_id,
@@ -453,7 +458,6 @@ class LLViewerMediaImpl
 	S32 mProximity;
 	F64 mProximityDistance;
 	F64 mProximityCamera;
-	LLMimeDiscoveryResponder *mMimeTypeProbe;
 	bool mMediaAutoPlay;
 	std::string mMediaEntryURL;
 	bool mInNearbyMediaList;	// used by LLPanelNearbyMedia::refreshList() for performance reasons
@@ -470,6 +474,10 @@ class LLViewerMediaImpl
 	BOOL mIsUpdated ;
 	std::list< LLVOVolume* > mObjectList ;
 
+    void mimeDiscoveryCoro(LLCoros::self& self, std::string url);
+    LLCoreHttpUtil::HttpCoroutineAdapter::wptr_t mMimeProbe;
+    bool mCanceling;
+
 private:
 	LLViewerMediaTexture *updatePlaceholderImage();
 };
diff --git a/indra/newview/llwebprofile.cpp b/indra/newview/llwebprofile.cpp
index df5f4e35888108b79532b1aa31a2e901c2e244a2..a72deafe33b431a0c40f0a3a61b41ac413bc1ee6 100755
--- a/indra/newview/llwebprofile.cpp
+++ b/indra/newview/llwebprofile.cpp
@@ -202,7 +202,7 @@ void LLWebProfile::uploadImageCoro(LLCoros::self& self, LLPointer<LLImageFormatt
 /*static*/
 LLCore::BufferArray::ptr_t LLWebProfile::buildPostData(const LLSD &data, LLPointer<LLImageFormatted> &image, const std::string &boundary)
 {
-    LLCore::BufferArray::ptr_t body(new LLCore::BufferArray);
+    LLCore::BufferArray::ptr_t body(new LLCore::BufferArray, false);
     LLCore::BufferArrayStream bas(body.get());
 
     // *NOTE: The order seems to matter.