1
+ /* **
2
+ * ==++==
3
+ *
4
+ * Copyright (c) Microsoft Corporation. All rights reserved.
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ *
16
+ * ==--==
17
+ * =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
18
+ *
19
+ * http_headers.h
20
+ *
21
+ * For the latest on this and related APIs, please see http://casablanca.codeplex.com.
22
+ *
23
+ * =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
24
+ ****/
25
+ #pragma once
26
+
27
+ #ifndef _CASA_HTTP_HEADERS_H
28
+ #define _CASA_HTTP_HEADERS_H
29
+
30
+ #include < map>
31
+ #include < memory>
32
+ #include < string>
33
+ #include < vector>
34
+ #include < system_error>
35
+ #include " cpprest/xxpublic.h"
36
+ #include " cpprest/asyncrt_utils.h"
37
+
38
+ namespace web { namespace http {
39
+
40
+ // / <summary>
41
+ // / Binds an individual reference to a string value.
42
+ // / </summary>
43
+ // / <typeparam name="key_type">The type of string value.</typeparam>
44
+ // / <typeparam name="_t">The type of the value to bind to.</typeparam>
45
+ // / <param name="text">The string value.</param>
46
+ // / <param name="ref">The value to bind to.</param>
47
+ // / <returns><c>true</c> if the binding succeeds, <c>false</c> otherwise.</returns>
48
+ template <typename key_type, typename _t>
49
+ bool bind (const key_type &text, _t &ref) // const
50
+ {
51
+ utility::istringstream_t iss (text);
52
+ iss >> ref;
53
+ if (iss.fail () || !iss.eof ())
54
+ {
55
+ return false ;
56
+ }
57
+
58
+ return true ;
59
+ }
60
+
61
+ // / <summary>
62
+ // / Binds an individual reference to a string value.
63
+ // / This specialization is need because <c>istringstream::>></c> delimits on whitespace.
64
+ // / </summary>
65
+ // / <typeparam name="key_type">The type of the string value.</typeparam>
66
+ // / <param name="text">The string value.</param>
67
+ // / <param name="ref">The value to bind to.</param>
68
+ // / <returns><c>true</c> if the binding succeeds, <c>false</c> otherwise.</returns>
69
+ template <typename key_type>
70
+ bool bind (const key_type &text, utility::string_t &ref) // const
71
+ {
72
+ ref = text;
73
+ return true ;
74
+ }
75
+
76
+ // / <summary>
77
+ // / Represents HTTP headers, acts like a map.
78
+ // / </summary>
79
+ class http_headers
80
+ {
81
+ public:
82
+ // / Function object to perform case insensitive comparison of wstrings.
83
+ struct _case_insensitive_cmp
84
+ {
85
+ bool operator ()(const utility::string_t &str1, const utility::string_t &str2) const
86
+ {
87
+ #ifdef _MS_WINDOWS
88
+ return _wcsicmp (str1.c_str (), str2.c_str ()) < 0 ;
89
+ #else
90
+ return utility::cmp::icmp (str1, str2) < 0 ;
91
+ #endif
92
+ }
93
+ };
94
+
95
+ // / <summary>
96
+ // / STL-style typedefs
97
+ // / </summary>
98
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::key_type key_type;
99
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::key_compare key_compare;
100
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::allocator_type allocator_type;
101
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::size_type size_type;
102
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::difference_type difference_type;
103
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::pointer pointer;
104
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::const_pointer const_pointer;
105
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::reference reference;
106
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::const_reference const_reference;
107
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::iterator iterator;
108
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::const_iterator const_iterator;
109
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::reverse_iterator reverse_iterator;
110
+ typedef std::map<utility::string_t , utility::string_t , _case_insensitive_cmp>::const_reverse_iterator const_reverse_iterator;
111
+
112
+ // / <summary>
113
+ // / Constructs an empty set of HTTP headers.
114
+ // / </summary>
115
+ http_headers () {}
116
+
117
+ // / <summary>
118
+ // / Copy constructor.
119
+ // / </summary>
120
+ // / <param name="other">An <c>http_headers</c> object to copy from.</param>
121
+ http_headers (const http_headers &other) : m_headers(other.m_headers) {}
122
+
123
+ // / <summary>
124
+ // / Assignment operator.
125
+ // / </summary>
126
+ // / <param name="other">An <c>http_headers</c> object to copy from.</param>
127
+ http_headers &operator =(const http_headers &other)
128
+ {
129
+ if (this != &other)
130
+ {
131
+ m_headers = other.m_headers ;
132
+ }
133
+ return *this ;
134
+ }
135
+
136
+ // / <summary>
137
+ // / Move constructor.
138
+ // / </summary>
139
+ // / <param name="other">An <c>http_headers</c> object to move.</param>
140
+ http_headers (http_headers &&other) : m_headers(std::move(other.m_headers)) {}
141
+
142
+ // / <summary>
143
+ // / Move assignment operator.
144
+ // / </summary>
145
+ // / <param name="other">An <c>http_headers</c> object to move.</param>
146
+ http_headers &operator =(http_headers &&other)
147
+ {
148
+ if (this != &other)
149
+ {
150
+ m_headers = std::move (other.m_headers );
151
+ }
152
+ return *this ;
153
+ }
154
+
155
+ // / <summary>
156
+ // / Adds a header field using the '<<' operator.
157
+ // / </summary>
158
+ // / <param name="name">The name of the header field.</param>
159
+ // / <param name="value">The value of the header field.</param>
160
+ // / <remark>If the header field exists, the value will be combined as comma separated string.</remark>
161
+ template <typename _t1>
162
+ void add (const key_type& name, const _t1& value)
163
+ {
164
+ if (has (name))
165
+ {
166
+ m_headers[name] = m_headers[name].append (_XPLATSTR (" , " ) + utility::conversions::print_string (value));
167
+ }
168
+ else
169
+ {
170
+ m_headers[name] = utility::conversions::print_string (value);
171
+ }
172
+ }
173
+
174
+ // / <summary>
175
+ // / Removes a header field.
176
+ // / </summary>
177
+ // / <param name="name">The name of the header field.</param>
178
+ void remove (const key_type& name)
179
+ {
180
+ m_headers.erase (name);
181
+ }
182
+
183
+ // / <summary>
184
+ // / Removes all elements from the hearders
185
+ // / </summary>
186
+ void clear () { m_headers.clear (); }
187
+
188
+ // / <summary>
189
+ // / Checks if there is a header with the given key.
190
+ // / </summary>
191
+ // / <param name="name">The name of the header field.</param>
192
+ // / <returns><c>true</c> if there is a header with the given name, <c>false</c> otherwise.</returns>
193
+ bool has (const key_type& name) const { return m_headers.find (name) != m_headers.end (); }
194
+
195
+ // / <summary>
196
+ // / Returns the number of header fields.
197
+ // / </summary>
198
+ // / <returns>Number of header fields.</returns>
199
+ size_type size () const { return m_headers.size (); }
200
+
201
+ // / <summary>
202
+ // / Tests to see if there are any header fields.
203
+ // / </summary>
204
+ // / <returns><c>true</c> if there are no headers, <c>false</c> otherwise.</returns>
205
+ bool empty () const { return m_headers.empty (); }
206
+
207
+ // / <summary>
208
+ // / Returns a reference to header field with given name, if there is no header field one is inserted.
209
+ // / </summary>
210
+ utility::string_t & operator [](const key_type &name) { return m_headers[name]; }
211
+
212
+ // / <summary>
213
+ // / Checks if a header field exists with given name and returns an iterator if found. Otherwise
214
+ // / and iterator to end is returned.
215
+ // / </summary>
216
+ // / <param name="name">The name of the header field.</param>
217
+ // / <returns>An iterator to where the HTTP header is found.</returns>
218
+ iterator find (const key_type &name) { return m_headers.find (name); }
219
+ const_iterator find (const key_type &name) const { return m_headers.find (name); }
220
+
221
+ // / <summary>
222
+ // / Attempts to match a header field with the given name using the '>>' operator.
223
+ // / </summary>
224
+ // / <param name="name">The name of the header field.</param>
225
+ // / <param name="value">The value of the header field.</param>
226
+ // / <returns><c>true</c> if header field was found and successfully stored in value parameter.</returns>
227
+ template <typename _t1>
228
+ bool match (const key_type &name, _t1 &value) const
229
+ {
230
+ auto iter = m_headers.find (name);
231
+ if (iter != m_headers.end ())
232
+ {
233
+ // Check to see if doesn't have a value.
234
+ if (iter->second .empty ())
235
+ {
236
+ http::bind (iter->second , value);
237
+ return true ;
238
+ }
239
+ return http::bind (iter->second , value);
240
+ }
241
+ else
242
+ {
243
+ return false ;
244
+ }
245
+ }
246
+
247
+ // / <summary>
248
+ // / Returns an iterator refering to the first header field.
249
+ // / </summary>
250
+ // / <returns>An iterator to the beginning of the HTTP headers</returns>
251
+ iterator begin () { return m_headers.begin (); }
252
+ const_iterator begin () const { return m_headers.begin (); }
253
+
254
+ // / <summary>
255
+ // / Returns an iterator referring to the past-the-end header field.
256
+ // / </summary>
257
+ // / <returns>An iterator to the element past the end of the HTTP headers</returns>
258
+ iterator end () { return m_headers.end (); }
259
+ const_iterator end () const { return m_headers.end (); }
260
+
261
+ // / <summary>
262
+ // / Gets the content length of the message.
263
+ // / </summary>
264
+ // / <returns>The length of the content.</returns>
265
+ _ASYNCRTIMP utility::size64_t content_length () const ;
266
+
267
+ // / <summary>
268
+ // / Sets the content length of the message.
269
+ // / </summary>
270
+ // / <param name="length">The length of the content.</param>
271
+ _ASYNCRTIMP void set_content_length (utility::size64_t length);
272
+
273
+ // / <summary>
274
+ // / Gets the content type of the message.
275
+ // / </summary>
276
+ // / <returns>The content type of the body.</returns>
277
+ _ASYNCRTIMP utility::string_t content_type () const ;
278
+
279
+ // / <summary>
280
+ // / Sets the content type of the message.
281
+ // / </summary>
282
+ // / <param name="type">The content type of the body.</param>
283
+ _ASYNCRTIMP void set_content_type (utility::string_t type);
284
+
285
+ // / <summary>
286
+ // / Gets the cache control header of the message.
287
+ // / </summary>
288
+ // / <returns>The cache control header value.</returns>
289
+ _ASYNCRTIMP utility::string_t cache_control () const ;
290
+
291
+ // / <summary>
292
+ // / Sets the cache control header of the message.
293
+ // / </summary>
294
+ // / <param name="control">The cache control header value.</param>
295
+ _ASYNCRTIMP void set_cache_control (utility::string_t control);
296
+
297
+ // / <summary>
298
+ // / Gets the date header of the message.
299
+ // / </summary>
300
+ // / <returns>The date header value.</returns>
301
+ _ASYNCRTIMP utility::string_t date () const ;
302
+
303
+ // / <summary>
304
+ // / Sets the date header of the message.
305
+ // / </summary>
306
+ // / <param name="date">The date header value.</param>
307
+ _ASYNCRTIMP void set_date (const utility::datetime& date);
308
+
309
+ private:
310
+
311
+ // Headers are stored in a map with case insensitive key.
312
+ std::map<utility::string_t , utility::string_t , _case_insensitive_cmp> m_headers;
313
+ };
314
+
315
+ }}
316
+ #endif
0 commit comments