summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcorehttp/_httplibcurl.cpp17
-rw-r--r--indra/llcorehttp/_httpoprequest.cpp14
-rw-r--r--indra/llcorehttp/examples/http_texture_load.cpp4
-rw-r--r--indra/llcorehttp/httpheaders.cpp141
-rw-r--r--indra/llcorehttp/httpheaders.h112
-rw-r--r--indra/llcorehttp/tests/test_httpheaders.hpp345
-rw-r--r--indra/llcorehttp/tests/test_httprequest.hpp563
-rwxr-xr-xindra/newview/llhttpretrypolicy.cpp20
-rwxr-xr-xindra/newview/lltexturefetch.cpp17
-rwxr-xr-xindra/newview/lltexturefetch.h3
-rwxr-xr-xindra/newview/tests/llhttpretrypolicy_test.cpp4
11 files changed, 1062 insertions, 178 deletions
diff --git a/indra/llcorehttp/_httplibcurl.cpp b/indra/llcorehttp/_httplibcurl.cpp
index 9ea831a771..d49f615ac4 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 74fc5c393a..95e0f72c0b 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 40ad4f047d..909dc5b0cb 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 2832696271..23ebea361c 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 3449daa3a1..f70cd898f3 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
@@ -64,6 +77,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
/// the instance.
@@ -76,7 +99,78 @@ protected:
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 ce0d19b058..668c36dc66 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 e5488cf941..27d65f171e 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/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp
index 82f6eab00e..10b923be5a 100755
--- a/indra/newview/llhttpretrypolicy.cpp
+++ b/indra/newview/llhttpretrypolicy.cpp
@@ -47,24 +47,13 @@ bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header
bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time)
{
- // Look for matching header. Hopefully it's correct enough to let
- // us extract the field we are looking for. Does not purport to be
- // in any way a viable general HTTP header parser.
if (headers)
{
- for (std::vector<std::string>::const_iterator it = headers->mHeaders.begin();
- it != headers->mHeaders.end();
- ++it)
+ const std::string *retry_value = headers->find(HTTP_IN_HEADER_RETRY_AFTER.c_str());
+ if (retry_value &&
+ getSecondsUntilRetryAfter(*retry_value, retry_header_time))
{
- const std::string& str = *it;
- const std::string match = HTTP_IN_HEADER_RETRY_AFTER + ":";
- size_t pos = str.find(match);
- if ((pos != std::string::npos) &&
- (pos+match.length() <= str.length()))
- {
- retry_header_time = strtod(str.substr(pos+match.length()).c_str(), NULL);
- return true;
- }
+ return true;
}
}
return false;
@@ -77,7 +66,6 @@ void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers)
onFailureCommon(status, has_retry_header_time, retry_header_time);
}
-// TODO: replace this parsing junk once CoreHttp has its own header parsing capabilities.
void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response)
{
F32 retry_header_time;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 7b719190a4..ce7bd61ce4 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
@@ -2480,6 +2480,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),
@@ -2510,11 +2511,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();
}
@@ -2535,6 +2538,12 @@ LLTextureFetch::~LLTextureFetch()
mHttpOptions = NULL;
}
+ if (mHttpOptionsWithHeaders)
+ {
+ mHttpOptionsWithHeaders->release();
+ mHttpOptionsWithHeaders = NULL;
+ }
+
if (mHttpHeaders)
{
mHttpHeaders->release();
@@ -4143,7 +4152,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 5e2b55dbbb..237912cde7 100755
--- 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
@@ -352,6 +352,7 @@ private:
// 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*
diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp
index 43fc1178cc..42bb9abe90 100755
--- a/indra/newview/tests/llhttpretrypolicy_test.cpp
+++ b/indra/newview/tests/llhttpretrypolicy_test.cpp
@@ -256,7 +256,7 @@ void RetryPolicyTestObject::test<7>()
LLCore::HttpHeaders *headers = new LLCore::HttpHeaders();
response->setStatus(503);
response->setHeaders(headers);
- headers->mHeaders.push_back(HTTP_IN_HEADER_RETRY_AFTER + ": 600");
+ headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600"));
policy.onFailure(response);
should_retry = policy.shouldRetry(seconds_to_wait);
ensure("header 3",should_retry);
@@ -272,7 +272,7 @@ void RetryPolicyTestObject::test<7>()
response->setHeaders(headers);
LLSD sd_headers;
time(&nowseconds);
- headers->mHeaders.push_back(HTTP_IN_HEADER_RETRY_AFTER + ": " + LLDate((F64)nowseconds).asRFC1123());
+ headers->append(HTTP_IN_HEADER_RETRY_AFTER,LLDate((F64)nowseconds).asRFC1123());
policy.onFailure(response);
should_retry = policy.shouldRetry(seconds_to_wait);
ensure("header 4",should_retry);