SH-4061 - integrated LLHttpRetryPolicy with new corehttp header parsing

meow-7.2.2
Brad Payne (Vir Linden) 2013-04-15 18:58:58 -04:00
commit 8d3afb35d8
11 changed files with 1062 additions and 178 deletions

View File

@ -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;
}

View File

@ -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));

View File

@ -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");
}

View File

@ -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

View File

@ -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 @@ 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

View File

@ -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->mHeaders.size());
ensure("First is first", headers->mHeaders[0] == str1);
ensure("Second is second", headers->mHeaders[1] == str2);
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");
}
// 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

View File

@ -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/",

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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*

View File

@ -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);