summaryrefslogtreecommitdiff
path: root/indra/llcorehttp/httpheaders.h
blob: 940f92183ced7458d0264b14cbea07caae8499e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/**
 * @file httpheaders.h
 * @brief Public-facing declarations for the HttpHeaders class
 *
 * $LicenseInfo:firstyear=2012&license=viewerlgpl$
 * Second Life Viewer Source Code
 * 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
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#ifndef	_LLCORE_HTTP_HEADERS_H_
#define	_LLCORE_HTTP_HEADERS_H_


#include "httpcommon.h"
#include <string>
#include "_refcounted.h"


namespace LLCore
{

///
/// Maintains an ordered list of name/value pairs representing
/// HTTP header lines.  This is used both to provide additional
/// headers when making HTTP requests and in responses when the
/// caller has asked that headers be returned (not the default
/// option).
///
/// 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
/// via reference counting with the worker thread.  The implication
/// is that once an HttpHeader instance is handed to a request,
/// the object must be treated as read-only.
///
/// Allocation:  Refcounted, heap only.  Caller of the
/// constructor is given a refcount.
///

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.
	HttpHeaders();

	typedef boost::intrusive_ptr<HttpHeaders> ptr_t;
protected:
	virtual ~HttpHeaders();						// Use release()

	HttpHeaders(const HttpHeaders &);			// Not defined
	void operator=(const HttpHeaders &);		// Not defined

public:
	// 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 std::string &name) const;
	const std::string * find(const char * name) const
	{
		return find(std::string(name));
	}

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

}  // end namespace LLCore


#endif	// _LLCORE_HTTP_HEADERS_H_