From 4eef1c8a2e2a8abcc463b9df38b66f025da57589 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Mon, 15 Apr 2013 16:55:35 +0000 Subject: SH-4106 Significantly upgrade the HttpHeaders interface for SSB. Header container moves from a vector of raw lines to a vector of string pairs representing name/value pairs in headers. For incoming headers, we normalize the name to lowercase and trim it. Values are only left-trimmed. Outgoing headers are left as-is. Simple find() method for the common case, forward and reverse iterators for those few who need to do it themselves. The HTTP status line (e.g. 'HTTP/1.1 200 Ok') is no longer treated as a header to be returned to caller. Unit tests, as usual, were a bear but they absolutely ensured outgoing HTTP header conformance after the change. Grunt work paid off. LLTextureFetch was also given a second options structure for texture fetches. Same as the original but with header return to caller requested. Baked textures should use this, the other 20,000 texture fetch requests should continue to use the original. --- indra/llcorehttp/httpheaders.h | 112 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 9 deletions(-) (limited to 'indra/llcorehttp/httpheaders.h') diff --git a/indra/llcorehttp/httpheaders.h b/indra/llcorehttp/httpheaders.h index 3449daa3a1..f70cd898f3 100755 --- a/indra/llcorehttp/httpheaders.h +++ b/indra/llcorehttp/httpheaders.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2012&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. + * Copyright (C) 2012-2013, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -43,13 +43,26 @@ namespace LLCore /// caller has asked that headers be returned (not the default /// option). /// -/// @note -/// This is a minimally-functional placeholder at the moment -/// to fill out the class hierarchy. The final class will be -/// something else, probably more pair-oriented. It's also -/// an area where shared values are desirable so refcounting is -/// already specced and a copy-on-write scheme imagined. -/// Expect changes here. +/// Class is mostly a thin wrapper around a vector of pairs +/// of strings. Methods provided are few and intended to +/// reflect actual use patterns. These include: +/// - Clearing the list +/// - Appending a name/value pair to the vector +/// - Processing a raw byte string into a normalized name/value +/// pair and appending the result. +/// - Simple case-sensitive find-last-by-name search +/// - Forward and reverse iterators over all pairs +/// +/// Container is ordered and multi-valued. Headers are +/// written in the order in which they are appended and +/// are stored in the order in which they're received from +/// the wire. The same header may appear two or more times +/// in any container. Searches using the simple find() +/// interface will find only the last occurrence (somewhat +/// simulates the use of std::map). Fuller searches require +/// the use of an iterator. Headers received from the wire +/// are only returned from the last request when redirections +/// are involved. /// /// Threading: Not intrinsically thread-safe. It *is* expected /// that callers will build these objects and then share them @@ -63,6 +76,16 @@ namespace LLCore class HttpHeaders : public LLCoreInt::RefCounted { +public: + typedef std::pair header_t; + typedef std::vector 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 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 -- cgit v1.2.3