diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 9ea831a771619f6feeaa6026437ab64869113137..d49f615ac42f007c073b8d6a56941e5a839e555c 100644
--- a/indra/llcorehttp/_httplibcurl.cpp
+++ b/indra/llcorehttp/_httplibcurl.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -359,12 +359,17 @@ int HttpLibcurl::getActiveCountInClass(int policy_class) const
 
 struct curl_slist * append_headers_to_slist(const HttpHeaders * headers, struct curl_slist * slist)
 {
-	for (HttpHeaders::container_t::const_iterator it(headers->mHeaders.begin());
-
-		headers->mHeaders.end() != it;
-		 ++it)
+	const HttpHeaders::const_iterator end(headers->end());
+	for (HttpHeaders::const_iterator it(headers->begin()); end != it; ++it)
 	{
-		slist = curl_slist_append(slist, (*it).c_str());
+		static const char sep[] = ": ";
+		std::string header;
+		header.reserve((*it).first.size() + (*it).second.size() + sizeof(sep));
+		header.append((*it).first);
+		header.append(sep);
+		header.append((*it).second);
+		
+		slist = curl_slist_append(slist, header.c_str());
 	}
 	return slist;
 }
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 74fc5c393a9ac6b58be3c72998d66d05dfaae989..95e0f72c0b09810dc1c2ac3b08c9e3b7ff1d9030 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -610,7 +610,8 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
 
 	const size_t hdr_size(size * nmemb);
 	const char * hdr_data(static_cast<const char *>(data));		// Not null terminated
-
+	bool is_header(true);
+	
 	if (hdr_size >= status_line_len && ! strncmp(status_line, hdr_data, status_line_len))
 	{
 		// One of possibly several status lines.  Reset what we know and start over
@@ -621,8 +622,9 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
 		op->mStatus = HttpStatus();
 		if (op->mReplyHeaders)
 		{
-			op->mReplyHeaders->mHeaders.clear();
+			op->mReplyHeaders->clear();
 		}
+		is_header = false;
 	}
 
 	// Nothing in here wants a final CR/LF combination.  Remove
@@ -637,18 +639,18 @@ size_t HttpOpRequest::headerCallback(void * data, size_t size, size_t nmemb, voi
 	}
 	
 	// Save header if caller wants them in the response
-	if (op->mProcFlags & PF_SAVE_HEADERS)
+	if (is_header && op->mProcFlags & PF_SAVE_HEADERS)
 	{
 		// Save headers in response
 		if (! op->mReplyHeaders)
 		{
 			op->mReplyHeaders = new HttpHeaders;
 		}
-		op->mReplyHeaders->mHeaders.push_back(std::string(hdr_data, wanted_hdr_size));
+		op->mReplyHeaders->appendNormal(hdr_data, wanted_hdr_size);
 	}
 
 	// Detect and parse 'Content-Range' headers
-	if (op->mProcFlags & PF_SCAN_RANGE_HEADER)
+	if (is_header && op->mProcFlags & PF_SCAN_RANGE_HEADER)
 	{
 		char hdr_buffer[128];			// Enough for a reasonable header
 		size_t frag_size((std::min)(wanted_hdr_size, sizeof(hdr_buffer) - 1));
diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp
index 40ad4f047dfcc0141cadaa25eb638bd6f278f8af..909dc5b0cb0f63b6de8792357af881e04151f136 100644
--- a/indra/llcorehttp/examples/http_texture_load.cpp
+++ b/indra/llcorehttp/examples/http_texture_load.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -328,7 +328,7 @@ WorkingSet::WorkingSet()
 	mTextures.reserve(30000);
 
 	mHeaders = new LLCore::HttpHeaders;
-	mHeaders->mHeaders.push_back("Accept: image/x-j2c");
+	mHeaders->append("Accept", "image/x-j2c");
 }
 
 
diff --git a/indra/llcorehttp/httpheaders.cpp b/indra/llcorehttp/httpheaders.cpp
index 2832696271440cb3681a4a5186670a31862d433d..23ebea361c1246b7589918cab569e2527be70d5e 100644
--- a/indra/llcorehttp/httpheaders.cpp
+++ b/indra/llcorehttp/httpheaders.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -26,6 +26,8 @@
 
 #include "httpheaders.h"
 
+#include "llstring.h"
+
 
 namespace LLCore
 {
@@ -40,5 +42,142 @@ HttpHeaders::~HttpHeaders()
 {}
 
 
+void
+HttpHeaders::clear()
+{
+	mHeaders.clear();
+}
+
+
+void HttpHeaders::append(const std::string & name, const std::string & value)
+{
+	mHeaders.push_back(value_type(name, value));
+}
+
+
+void HttpHeaders::append(const char * name, const char * value)
+{
+	mHeaders.push_back(value_type(name, value));
+}
+
+
+void HttpHeaders::appendNormal(const char * header, size_t size)
+{
+	std::string name;
+	std::string value;
+
+	int col_pos(0);
+	for (; col_pos < size; ++col_pos)
+	{
+		if (':' == header[col_pos])
+			break;
+	}
+	
+	if (col_pos < size)
+	{
+		// Looks like a header, split it and normalize.
+		// Name is everything before the colon, may be zero-length.
+		name.assign(header, col_pos);
+
+		// Value is everything after the colon, may also be zero-length.
+		const size_t val_len(size - col_pos - 1);
+		if (val_len)
+		{
+			value.assign(header + col_pos + 1, val_len);
+		}
+
+		// Clean the strings
+		LLStringUtil::toLower(name);
+		LLStringUtil::trim(name);
+		LLStringUtil::trimHead(value);
+	}
+	else
+	{
+		// Uncertain what this is, we'll pack it as
+		// a name without a value.  Won't clean as we don't
+		// know what it is...
+		name.assign(header, size);
+	}
+
+	mHeaders.push_back(value_type(name, value));
+}
+
+
+// Find from end to simulate a tradition of using single-valued
+// std::map for this in the past.
+const std::string * HttpHeaders::find(const char * name) const
+{
+	const_reverse_iterator iend(rend());
+	for (const_reverse_iterator iter(rbegin()); iend != iter; ++iter)
+	{
+		if ((*iter).first == name)
+		{
+			return &(*iter).second;
+		}
+	}
+	return NULL;
+}
+
+
+// Standard Iterators
+HttpHeaders::iterator HttpHeaders::begin()
+{
+	return mHeaders.begin();
+}
+
+
+HttpHeaders::const_iterator HttpHeaders::begin() const
+{
+	return mHeaders.begin();
+}
+
+
+HttpHeaders::iterator HttpHeaders::end()
+{
+	return mHeaders.end();
+}
+
+
+HttpHeaders::const_iterator HttpHeaders::end() const
+{
+	return mHeaders.end();
+}
+
+
+// Standard Reverse Iterators
+HttpHeaders::reverse_iterator HttpHeaders::rbegin()
+{
+	return mHeaders.rbegin();
+}
+
+
+HttpHeaders::const_reverse_iterator HttpHeaders::rbegin() const
+{
+	return mHeaders.rbegin();
+}
+
+
+HttpHeaders::reverse_iterator HttpHeaders::rend()
+{
+	return mHeaders.rend();
+}
+
+
+HttpHeaders::const_reverse_iterator HttpHeaders::rend() const
+{
+	return mHeaders.rend();
+}
+
+
+// Return the raw container to the caller.
+//
+// To be used FOR UNIT TESTS ONLY.
+//
+HttpHeaders::container_t & HttpHeaders::getContainerTESTONLY()
+{
+	return mHeaders;
+}
+
+
 }   // end namespace LLCore
 
diff --git a/indra/llcorehttp/httpheaders.h b/indra/llcorehttp/httpheaders.h
index 3449daa3a1311c859720cc1624c885420822a7c2..f70cd898f3949eb641991bd76fdd3650c5abe885 100644
--- a/indra/llcorehttp/httpheaders.h
+++ b/indra/llcorehttp/httpheaders.h
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -43,13 +43,26 @@ namespace LLCore
 /// caller has asked that headers be returned (not the default
 /// option).
 ///
-/// @note
-/// This is a minimally-functional placeholder at the moment
-/// to fill out the class hierarchy.  The final class will be
-/// something else, probably more pair-oriented.  It's also
-/// an area where shared values are desirable so refcounting is
-/// already specced and a copy-on-write scheme imagined.
-/// Expect changes here.
+/// Class is mostly a thin wrapper around a vector of pairs
+/// of strings.  Methods provided are few and intended to
+/// reflect actual use patterns.  These include:
+/// - Clearing the list
+/// - Appending a name/value pair to the vector
+/// - Processing a raw byte string into a normalized name/value
+///   pair and appending the result.
+/// - Simple case-sensitive find-last-by-name search
+/// - Forward and reverse iterators over all pairs
+///
+/// Container is ordered and multi-valued.  Headers are
+/// written in the order in which they are appended and
+/// are stored in the order in which they're received from
+/// the wire.  The same header may appear two or more times
+/// in any container.  Searches using the simple find()
+/// interface will find only the last occurrence (somewhat
+/// simulates the use of std::map).  Fuller searches require
+/// the use of an iterator.  Headers received from the wire
+/// are only returned from the last request when redirections
+/// are involved.
 ///
 /// Threading:  Not intrinsically thread-safe.  It *is* expected
 /// that callers will build these objects and then share them
@@ -63,6 +76,16 @@ namespace LLCore
 
 class HttpHeaders : public LLCoreInt::RefCounted
 {
+public:
+	typedef std::pair<std::string, std::string> header_t;
+	typedef std::vector<header_t> container_t;
+	typedef container_t::iterator iterator;
+	typedef container_t::const_iterator const_iterator;
+	typedef container_t::reverse_iterator reverse_iterator;
+	typedef container_t::const_reverse_iterator const_reverse_iterator;
+	typedef container_t::value_type value_type;
+	typedef container_t::size_type size_type;
+
 public:
 	/// @post In addition to the instance, caller has a refcount
 	/// to the instance.  A call to @see release() will destroy
@@ -76,7 +99,78 @@ class HttpHeaders : public LLCoreInt::RefCounted
 	void operator=(const HttpHeaders &);		// Not defined
 
 public:
-	typedef std::vector<std::string> container_t;
+	// Empty the list of headers.
+	void clear();
+
+	// Append a name/value pair supplied as either std::strings
+	// or NUL-terminated char * to the header list.  No normalization
+	// is performed on the strings.  No conformance test is
+	// performed (names may contain spaces, colons, etc.).
+	//
+	void append(const std::string & name, const std::string & value);
+	void append(const char * name, const char * value);
+
+	// Extract a name/value pair from a raw byte array using
+	// the first colon character as a separator.  Input string
+	// does not need to be NUL-terminated.  Resulting name/value
+	// pair is appended to the header list.
+	//
+	// Normalization is performed on the name/value pair as
+	// follows:
+	// - name is lower-cased according to mostly ASCII rules
+	// - name is left- and right-trimmed of spaces and tabs
+	// - value is left-trimmed of spaces and tabs
+	// - either or both of name and value may be zero-length
+	//
+	// By convention, headers read from the wire will be normalized
+	// in this fashion prior to delivery to any HttpHandler code.
+	// Headers to be written to the wire are left as appended to
+	// the list.
+	void appendNormal(const char * header, size_t size);
+
+	// Perform a simple, case-sensitive search of the header list
+	// returning a pointer to the value of the last matching header
+	// in the header list.  If none is found, a NULL pointer is returned.
+	//
+	// Any pointer returned references objects in the container itself
+	// and will have the same lifetime as this class.  If you want
+	// the value beyond the lifetime of this instance, make a copy.
+	//
+	// @arg		name	C-style string giving the name of a header
+	//					to search.  The comparison is case-sensitive
+	//					though list entries may have been normalized
+	//					to lower-case.
+	//
+	// @return			NULL if the header wasn't found otherwise
+	//					a pointer to a std::string in the container.
+	//					Pointer is valid only for the lifetime of
+	//					the container or until container is modifed.
+	//
+	const std::string * find(const char * name) const;
+
+	// Count of headers currently in the list.
+	size_type size() const
+		{
+			return mHeaders.size();
+		}
+
+	// Standard std::vector-based forward iterators.
+	iterator begin();
+	const_iterator begin() const;
+	iterator end();
+	const_iterator end() const;
+
+	// Standard std::vector-based reverse iterators.
+	reverse_iterator rbegin();
+	const_reverse_iterator rbegin() const;
+	reverse_iterator rend();
+	const_reverse_iterator rend() const;
+
+public:
+	// For unit tests only - not a public API
+	container_t &		getContainerTESTONLY();
+	
+protected:
 	container_t			mHeaders;
 	
 }; // end class HttpHeaders
diff --git a/indra/llcorehttp/tests/test_httpheaders.hpp b/indra/llcorehttp/tests/test_httpheaders.hpp
index ce0d19b05842bc49c55b98fd1eaa807a7a6aa681..668c36dc66bc142947a99546dee4ee6e152be5be 100644
--- a/indra/llcorehttp/tests/test_httpheaders.hpp
+++ b/indra/llcorehttp/tests/test_httpheaders.hpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -36,7 +36,6 @@
 using namespace LLCoreInt;
 
 
-
 namespace tut
 {
 
@@ -63,7 +62,7 @@ void HttpHeadersTestObjectType::test<1>()
 	HttpHeaders * headers = new HttpHeaders();
 	ensure("One ref on construction of HttpHeaders", headers->getRefCount() == 1);
 	ensure("Memory being used", mMemTotal < GetMemTotal());
-	ensure("Nothing in headers", 0 == headers->mHeaders.size());
+	ensure("Nothing in headers", 0 == headers->size());
 
 	// release the implicit reference, causing the object to be released
 	headers->release();
@@ -85,14 +84,340 @@ void HttpHeadersTestObjectType::test<2>()
 	
 	{
 		// Append a few strings
-		std::string str1("Pragma:");
-		headers->mHeaders.push_back(str1);
-		std::string str2("Accept: application/json");
-		headers->mHeaders.push_back(str2);
+		std::string str1n("Pragma");
+		std::string str1v("");
+		headers->append(str1n, str1v);
+		std::string str2n("Accept");
+		std::string str2v("application/json");
+		headers->append(str2n, str2v);
+	
+		ensure("Headers retained", 2 == headers->size());
+		HttpHeaders::container_t & c(headers->getContainerTESTONLY());
+		
+		ensure("First name is first name", c[0].first == str1n);
+		ensure("First value is first value", c[0].second == str1v);
+		ensure("Second name is second name", c[1].first == str2n);
+		ensure("Second value is second value", c[1].second == str2v);
+	}
+	
+	// release the implicit reference, causing the object to be released
+	headers->release();
+
+	// make sure we didn't leak any memory
+	ensure(mMemTotal == GetMemTotal());
+}
+
+template <> template <>
+void HttpHeadersTestObjectType::test<3>()
+{
+	set_test_name("HttpHeaders basic find");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	HttpHeaders * headers = new HttpHeaders();
+	
+	{
+		// Append a few strings
+		std::string str1n("Uno");
+		std::string str1v("1");
+		headers->append(str1n, str1v);
+		std::string str2n("doS");
+		std::string str2v("2-2-2-2");
+		headers->append(str2n, str2v);
+		std::string str3n("TRES");
+		std::string str3v("trois gymnopedie");
+		headers->append(str3n, str3v);
+	
+		ensure("Headers retained", 3 == headers->size());
+
+		const std::string * result(NULL);
+
+		// Find a header
+		result = headers->find("TRES");
+		ensure("Found the last item", result != NULL);
+		ensure("Last item is a nice", result != NULL && str3v == *result);
+
+		// appends above are raw and find is case sensitive
+		result = headers->find("TReS");
+		ensure("Last item not found due to case", result == NULL);
+
+		result = headers->find("TRE");
+		ensure("Last item not found due to prefixing (1)", result == NULL);
+
+		result = headers->find("TRESS");
+		ensure("Last item not found due to prefixing (2)", result == NULL);
+	}
+	
+	// release the implicit reference, causing the object to be released
+	headers->release();
+
+	// make sure we didn't leak any memory
+	ensure(mMemTotal == GetMemTotal());
+}
+
+template <> template <>
+void HttpHeadersTestObjectType::test<4>()
+{
+	set_test_name("HttpHeaders normalized header entry");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	HttpHeaders * headers = new HttpHeaders();
+	
+	{
+		static char line1[] = " AcCePT : image/yourfacehere";
+		static char line1v[] = "image/yourfacehere";
+		headers->appendNormal(line1, sizeof(line1) - 1);
+		
+		ensure("First append worked in some fashion", 1 == headers->size());
+
+		const std::string * result(NULL);
+
+		// Find a header
+		result = headers->find("accept");
+		ensure("Found 'accept'", result != NULL);
+		ensure("accept value has face", result != NULL && *result == line1v);
+
+		// Left-clean on value
+		static char line2[] = " next : \t\tlinejunk \t";
+		headers->appendNormal(line2, sizeof(line2) - 1);
+		ensure("Second append worked", 2 == headers->size());
+		result = headers->find("next");
+		ensure("Found 'next'", result != NULL);
+		ensure("next value is left-clean", result != NULL &&
+			   *result == "linejunk \t");
+
+		// First value unmolested
+		result = headers->find("accept");
+		ensure("Found 'accept' again", result != NULL);
+		ensure("accept value has face", result != NULL && *result == line1v);
+
+		// Colons in value are okay
+		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
+		static char line3v[] = ":plop:-neuf-=vleem=";
+		headers->appendNormal(line3, sizeof(line3) - 1);
+		ensure("Third append worked", 3 == headers->size());
+		result = headers->find("fancy-pants");
+		ensure("Found 'fancy-pants'", result != NULL);
+		ensure("fancy-pants value has colons", result != NULL && *result == line3v);
+
+		// Zero-length value
+		static char line4[] = "all-talk-no-walk:";
+		headers->appendNormal(line4, sizeof(line4) - 1);
+		ensure("Fourth append worked", 4 == headers->size());
+		result = headers->find("all-talk-no-walk");
+		ensure("Found 'all-talk'", result != NULL);
+		ensure("al-talk value is zero-length", result != NULL && result->size() == 0);
+
+		// Zero-length name
+		static char line5[] = ":all-talk-no-walk";
+		static char line5v[] = "all-talk-no-walk";
+		headers->appendNormal(line5, sizeof(line5) - 1);
+		ensure("Fifth append worked", 5 == headers->size());
+		result = headers->find("");
+		ensure("Found no-name", result != NULL);
+		ensure("no-name value is something", result != NULL && *result == line5v);
+
+		// Lone colon is still something
+		headers->clear();
+		static char line6[] = "  :";
+		headers->appendNormal(line6, sizeof(line6) - 1);
+		ensure("Sixth append worked", 1 == headers->size());
+		result = headers->find("");
+		ensure("Found 2nd no-name", result != NULL);
+		ensure("2nd no-name value is nothing", result != NULL && result->size() == 0);
+
+		// Line without colons is taken as-is and unstripped in name
+		static char line7[] = " \toskdgioasdghaosdghoowg28342908tg8902hg0hwedfhqew890v7qh0wdebv78q0wdevbhq>?M>BNM<ZV>?NZ? \t";
+		headers->appendNormal(line7, sizeof(line7) - 1);
+		ensure("Seventh append worked", 2 == headers->size());
+		result = headers->find(line7);
+		ensure("Found whatsit line", result != NULL);
+		ensure("Whatsit line has no value", result != NULL && result->size() == 0);
+
+		// Normaling interface heeds the byte count, doesn't look for NUL-terminator
+		static char line8[] = "binary:ignorestuffontheendofthis";
+		headers->appendNormal(line8, 13);
+		ensure("Eighth append worked", 3 == headers->size());
+		result = headers->find("binary");
+		ensure("Found 'binary'", result != NULL);
+		ensure("binary value was limited to 'ignore'", result != NULL &&
+			   *result == "ignore");
+
+	}
 	
-		ensure("Headers retained", 2 == headers->mHeaders.size());
-		ensure("First is first", headers->mHeaders[0] == str1);
-		ensure("Second is second", headers->mHeaders[1] == str2);
+	// release the implicit reference, causing the object to be released
+	headers->release();
+
+	// make sure we didn't leak any memory
+	ensure(mMemTotal == GetMemTotal());
+}
+
+// Verify forward iterator finds everything as expected
+template <> template <>
+void HttpHeadersTestObjectType::test<5>()
+{
+	set_test_name("HttpHeaders iterator tests");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	HttpHeaders * headers = new HttpHeaders();
+
+	HttpHeaders::iterator end(headers->end()), begin(headers->begin());
+	ensure("Empty container has equal begin/end const iterators", end == begin);
+	HttpHeaders::const_iterator cend(headers->end()), cbegin(headers->begin());
+	ensure("Empty container has equal rbegin/rend const iterators", cend == cbegin);
+
+	ensure("Empty container has equal begin/end iterators", headers->end() == headers->begin());
+	
+	{
+		static char line1[] = " AcCePT : image/yourfacehere";
+		static char line1v[] = "image/yourfacehere";
+		headers->appendNormal(line1, sizeof(line1) - 1);
+
+		static char line2[] = " next : \t\tlinejunk \t";
+		static char line2v[] = "linejunk \t";
+		headers->appendNormal(line2, sizeof(line2) - 1);
+
+		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
+		static char line3v[] = ":plop:-neuf-=vleem=";
+		headers->appendNormal(line3, sizeof(line3) - 1);
+
+		static char line4[] = "all-talk-no-walk:";
+		static char line4v[] = "";
+		headers->appendNormal(line4, sizeof(line4) - 1);
+
+		static char line5[] = ":all-talk-no-walk";
+		static char line5v[] = "all-talk-no-walk";
+		headers->appendNormal(line5, sizeof(line5) - 1);
+
+		static char line6[] = "  :";
+		static char line6v[] = "";
+		headers->appendNormal(line6, sizeof(line6) - 1);
+
+		ensure("All entries accounted for", 6 == headers->size());
+
+		static char * values[] = {
+			line1v,
+			line2v,
+			line3v,
+			line4v,
+			line5v,
+			line6v
+		};
+			
+		int i(0);
+		HttpHeaders::const_iterator cend(headers->end());
+		for (HttpHeaders::const_iterator it(headers->begin());
+			 cend != it;
+			 ++it, ++i)
+		{
+			std::ostringstream str;
+			str << "Const Iterator value # " << i << " was " << values[i];
+			ensure(str.str(), (*it).second == values[i]);
+		}
+
+		// Rewind, do non-consts
+		i = 0;
+		HttpHeaders::iterator end(headers->end());
+		for (HttpHeaders::iterator it(headers->begin());
+			 end != it;
+			 ++it, ++i)
+		{
+			std::ostringstream str;
+			str << "Const Iterator value # " << i << " was " << values[i];
+			ensure(str.str(), (*it).second == values[i]);
+		}
+	}
+	
+	// release the implicit reference, causing the object to be released
+	headers->release();
+
+	// make sure we didn't leak any memory
+	ensure(mMemTotal == GetMemTotal());
+}
+
+// Reverse iterators find everything as expected
+template <> template <>
+void HttpHeadersTestObjectType::test<6>()
+{
+	set_test_name("HttpHeaders reverse iterator tests");
+
+	// record the total amount of dynamically allocated memory
+	mMemTotal = GetMemTotal();
+
+	// create a new ref counted object with an implicit reference
+	HttpHeaders * headers = new HttpHeaders();
+
+	HttpHeaders::reverse_iterator rend(headers->rend()), rbegin(headers->rbegin());
+	ensure("Empty container has equal rbegin/rend const iterators", rend == rbegin);
+	HttpHeaders::const_reverse_iterator crend(headers->rend()), crbegin(headers->rbegin());
+	ensure("Empty container has equal rbegin/rend const iterators", crend == crbegin);
+	
+	{
+		static char line1[] = " AcCePT : image/yourfacehere";
+		static char line1v[] = "image/yourfacehere";
+		headers->appendNormal(line1, sizeof(line1) - 1);
+
+		static char line2[] = " next : \t\tlinejunk \t";
+		static char line2v[] = "linejunk \t";
+		headers->appendNormal(line2, sizeof(line2) - 1);
+
+		static char line3[] = "FancY-PANTs::plop:-neuf-=vleem=";
+		static char line3v[] = ":plop:-neuf-=vleem=";
+		headers->appendNormal(line3, sizeof(line3) - 1);
+
+		static char line4[] = "all-talk-no-walk:";
+		static char line4v[] = "";
+		headers->appendNormal(line4, sizeof(line4) - 1);
+
+		static char line5[] = ":all-talk-no-walk";
+		static char line5v[] = "all-talk-no-walk";
+		headers->appendNormal(line5, sizeof(line5) - 1);
+
+		static char line6[] = "  :";
+		static char line6v[] = "";
+		headers->appendNormal(line6, sizeof(line6) - 1);
+
+		ensure("All entries accounted for", 6 == headers->size());
+
+		static char * values[] = {
+			line6v,
+			line5v,
+			line4v,
+			line3v,
+			line2v,
+			line1v
+		};
+			
+		int i(0);
+		HttpHeaders::const_reverse_iterator cend(headers->rend());
+		for (HttpHeaders::const_reverse_iterator it(headers->rbegin());
+			 cend != it;
+			 ++it, ++i)
+		{
+			std::ostringstream str;
+			str << "Const Iterator value # " << i << " was " << values[i];
+			ensure(str.str(), (*it).second == values[i]);
+		}
+
+		// Rewind, do non-consts
+		i = 0;
+		HttpHeaders::reverse_iterator end(headers->rend());
+		for (HttpHeaders::reverse_iterator it(headers->rbegin());
+			 end != it;
+			 ++it, ++i)
+		{
+			std::ostringstream str;
+			str << "Iterator value # " << i << " was " << values[i];
+			ensure(str.str(), (*it).second == values[i]);
+		}
 	}
 	
 	// release the implicit reference, causing the object to be released
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index e5488cf941e7a8b7c0892965aa6664d596a44edf..27d65f171ecb483541933c18657b02bbdac05d7b 100644
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2012&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -60,6 +60,8 @@ void usleep(unsigned long usec);
 namespace tut
 {
 
+typedef std::vector<std::pair<boost::regex, boost::regex> > regex_container_t;
+
 struct HttpRequestTestData
 {
 	// the test objects inherit from this so the member functions and variables
@@ -109,11 +111,17 @@ public:
 					for (int i(0); i < mHeadersRequired.size(); ++i)
 					{
 						bool found = false;
-						for (HttpHeaders::container_t::const_iterator iter(header->mHeaders.begin());
-							 header->mHeaders.end() != iter;
+						for (HttpHeaders::const_iterator iter(header->begin());
+							 header->end() != iter;
 							 ++iter)
 						{
-							if (boost::regex_match(*iter, mHeadersRequired[i]))
+							// std::cerr << "Header: " << (*iter).first
+							//		  << ": " << (*iter).second << std::endl;
+							
+							if (boost::regex_match((*iter).first,
+												   mHeadersRequired[i].first) &&
+								boost::regex_match((*iter).second,
+												   mHeadersRequired[i].second))
 							{
 								found = true;
 								break;
@@ -129,11 +137,14 @@ public:
 				{
 					for (int i(0); i < mHeadersDisallowed.size(); ++i)
 					{
-						for (HttpHeaders::container_t::const_iterator iter(header->mHeaders.begin());
-							 header->mHeaders.end() != iter;
+						for (HttpHeaders::const_iterator iter(header->begin());
+							 header->end() != iter;
 							 ++iter)
 						{
-							if (boost::regex_match(*iter, mHeadersDisallowed[i]))
+							if (boost::regex_match((*iter).first,
+												   mHeadersDisallowed[i].first) &&
+								boost::regex_match((*iter).second,
+												   mHeadersDisallowed[i].second))
 							{
 								std::ostringstream str;
 								str << "Disallowed header # " << i << " not found in response";
@@ -159,8 +170,8 @@ public:
 	std::string mName;
 	HttpHandle mExpectHandle;
 	std::string mCheckContentType;
-	std::vector<boost::regex> mHeadersRequired;
-	std::vector<boost::regex> mHeadersDisallowed;
+	regex_container_t mHeadersRequired;
+	regex_container_t mHeadersDisallowed;
 };
 
 typedef test_group<HttpRequestTestData> HttpRequestTestGroupType;
@@ -1335,7 +1346,9 @@ void HttpRequestTestObjectType::test<13>()
 		
 		// Issue a GET that succeeds
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("\\W*X-LL-Special:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(boost::regex("X-LL-Special", boost::regex::icase),
+										  boost::regex(".*", boost::regex::icase)));
 		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
 													 0U,
 													 url_base,
@@ -1702,18 +1715,54 @@ void HttpRequestTestObjectType::test<16>()
 		
 		// Issue a GET that *can* connect
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
 		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base + "reflect/",
@@ -1735,23 +1784,60 @@ void HttpRequestTestObjectType::test<16>()
 
 		// Do a texture-style fetch
 		headers = new HttpHeaders;
-		headers->mHeaders.push_back("Accept: image/x-j2c");
+		headers->append("Accept", "image/x-j2c");
 		
 		mStatus = HttpStatus(200);
 		handler.mHeadersRequired.clear();
 		handler.mHeadersDisallowed.clear();
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*image/x-j2c", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("\\W*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("image/x-j2c", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("\\W*X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
 		handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
 										  0U,
 										  url_base + "reflect/",
@@ -1892,20 +1978,63 @@ void HttpRequestTestObjectType::test<17>()
 			
 		// Issue a default POST
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/x-www-form-urlencoded", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-length", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("application/x-www-form-urlencoded", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-expect", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer_encoding", boost::regex::icase),
+				boost::regex(".*chunked.*", boost::regex::icase)));
 		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
 											 0U,
 											 url_base + "reflect/",
@@ -2052,20 +2181,64 @@ void HttpRequestTestObjectType::test<18>()
 			
 		// Issue a default PUT
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-length", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-expect", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*chunked.*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+
 		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base + "reflect/",
@@ -2206,27 +2379,73 @@ void HttpRequestTestObjectType::test<19>()
 
 		// headers
 		headers = new HttpHeaders;
-		headers->mHeaders.push_back("Keep-Alive: 120");
-		headers->mHeaders.push_back("Accept-encoding: deflate");
-		headers->mHeaders.push_back("Accept: text/plain");
+		headers->append("Keep-Alive", "120");
+		headers->append("Accept-encoding", "deflate");
+		headers->append("Accept", "text/plain");
 
 		// Issue a GET with modified headers
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*text/plain", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*deflate", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*120", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-keep-alive:\\s*300", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-type:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("text/plain", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("deflate", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("120", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("300", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
 		HttpHandle handle = req->requestGet(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base + "reflect/",
@@ -2359,10 +2578,10 @@ void HttpRequestTestObjectType::test<20>()
 
 		// headers
 		headers = new HttpHeaders();
-		headers->mHeaders.push_back("keep-Alive: 120");
-		headers->mHeaders.push_back("Accept:  text/html");
-		headers->mHeaders.push_back("content-type:  application/llsd+xml");
-		headers->mHeaders.push_back("cache-control: no-store");
+		headers->append("keep-Alive", "120");
+		headers->append("Accept", "text/html");
+		headers->append("content-type", "application/llsd+xml");
+		headers->append("cache-control", "no-store");
 		
 		// And a buffer array
 		const char * msg("<xml><llsd><string>It was the best of times, it was the worst of times.</string></llsd></xml>");
@@ -2371,23 +2590,76 @@ void HttpRequestTestObjectType::test<20>()
 			
 		// Issue a default POST
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*text/html", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*120", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/llsd\\+xml", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("\\s*X-Reflect-cache-control:\\s*no-store", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*application/x-www-form-urlencoded", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-keep-alive:\\s*300", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("text/html", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("120", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-length", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("application/llsd\\+xml", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex("no-store", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("application/x-www-form-urlencoded", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("300", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-expect", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+
 		HttpHandle handle = req->requestPost(HttpRequest::DEFAULT_POLICY_ID,
 											 0U,
 											 url_base + "reflect/",
@@ -2529,9 +2801,9 @@ void HttpRequestTestObjectType::test<21>()
 
 		// headers
 		headers = new HttpHeaders;
-		headers->mHeaders.push_back("content-type:  text/plain");
-		headers->mHeaders.push_back("content-type:  text/html");
-		headers->mHeaders.push_back("content-type:  application/llsd+xml");
+		headers->append("content-type", "text/plain");
+		headers->append("content-type", "text/html");
+		headers->append("content-type", "application/llsd+xml");
 		
 		// And a buffer array
 		const char * msg("<xml><llsd><string>It was the best of times, it was the worst of times.</string></llsd></xml>");
@@ -2540,22 +2812,71 @@ void HttpRequestTestObjectType::test<21>()
 			
 		// Issue a default PUT
 		mStatus = HttpStatus(200);
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-connection:\\s*keep-alive", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept:\\s*\\*/\\*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-accept-encoding:\\s*((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase)); // close enough
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-keep-alive:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-host:\\s*.*", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-length:\\s*\\d+", boost::regex::icase));
-		handler.mHeadersRequired.push_back(boost::regex("X-Reflect-content-type:\\s*application/llsd\\+xml", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-cache-control:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-pragma:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-range:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-referer:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-content-encoding:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-expect:.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("\\s*X-Reflect-transfer-encoding:\\s*.*chunked.*", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*text/plain", boost::regex::icase));
-		handler.mHeadersDisallowed.push_back(boost::regex("X-Reflect-content-type:\\s*text/html", boost::regex::icase));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-connection", boost::regex::icase),
+				boost::regex("keep-alive", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept", boost::regex::icase),
+				boost::regex("\\*/\\*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-accept-encoding", boost::regex::icase),
+				boost::regex("((gzip|deflate),\\s*)+(gzip|deflate)", boost::regex::icase))); // close enough
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-keep-alive", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-host", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-length", boost::regex::icase),
+				boost::regex("\\d+", boost::regex::icase)));
+		handler.mHeadersRequired.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("application/llsd\\+xml", boost::regex::icase)));
+
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-cache-control", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-pragma", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-range", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-referer", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-expect", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-transfer-encoding", boost::regex::icase),
+				boost::regex(".*", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("text/plain", boost::regex::icase)));
+		handler.mHeadersDisallowed.push_back(
+			regex_container_t::value_type(
+				boost::regex("X-Reflect-content-type", boost::regex::icase),
+				boost::regex("text/html", boost::regex::icase)));
 		HttpHandle handle = req->requestPut(HttpRequest::DEFAULT_POLICY_ID,
 											0U,
 											url_base + "reflect/",
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index cc6dc64626ba160b5b9aeb979b8c34021ffa669a..5e12c341d51f776c229b85a9036bc0236e0ff8bf 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -2376,6 +2376,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	  mQAMode(qa_mode),
 	  mHttpRequest(NULL),
 	  mHttpOptions(NULL),
+	  mHttpOptionsWithHeaders(NULL),
 	  mHttpHeaders(NULL),
 	  mHttpMetricsHeaders(NULL),
 	  mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
@@ -2406,11 +2407,13 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
 	
 	mHttpRequest = new LLCore::HttpRequest;
 	mHttpOptions = new LLCore::HttpOptions;
+	mHttpOptionsWithHeaders = new LLCore::HttpOptions;
+	mHttpOptionsWithHeaders->setWantHeaders(true);
 	mHttpHeaders = new LLCore::HttpHeaders;
 	// *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ?
-	mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
+	mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
 	mHttpMetricsHeaders = new LLCore::HttpHeaders;
-	mHttpMetricsHeaders->mHeaders.push_back(HTTP_OUT_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML);
+	mHttpMetricsHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML);
 	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault();
 }
 
@@ -2431,6 +2434,12 @@ LLTextureFetch::~LLTextureFetch()
 		mHttpOptions = NULL;
 	}
 
+	if (mHttpOptionsWithHeaders)
+	{
+		mHttpOptionsWithHeaders->release();
+		mHttpOptionsWithHeaders = NULL;
+	}
+
 	if (mHttpHeaders)
 	{
 		mHttpHeaders->release();
@@ -4043,7 +4052,7 @@ void LLTextureFetchDebugger::init()
 	{
 		mHttpHeaders = new LLCore::HttpHeaders;
 		// *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ?
-		mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C);
+		mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C);
 	}
 }
 
diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h
index 902a3d7a25431054b235e171fc1504fbebac0927..3c79a5a24d7ed8eca0a8d1a04d085521a6850e62 100644
--- a/indra/newview/lltexturefetch.h
+++ b/indra/newview/lltexturefetch.h
@@ -4,7 +4,7 @@
  *
  * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
+ * Copyright (C) 2012-2013, 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
@@ -351,6 +351,7 @@ class LLTextureFetch : public LLWorkerThread
 	// LLCurl interfaces used in the past.
 	LLCore::HttpRequest *				mHttpRequest;					// Ttf
 	LLCore::HttpOptions *				mHttpOptions;					// Ttf
+	LLCore::HttpOptions *				mHttpOptionsWithHeaders;		// Ttf
 	LLCore::HttpHeaders *				mHttpHeaders;					// Ttf
 	LLCore::HttpHeaders *				mHttpMetricsHeaders;			// Ttf
 	LLCore::HttpRequest::policy_t		mHttpPolicyClass;				// T*