Skip to content

Commit c3bc0f7

Browse files
committed
Continuation of TFS merge
1 parent 45b4c2b commit c3bc0f7

File tree

5 files changed

+588
-0
lines changed

5 files changed

+588
-0
lines changed
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
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::&gt;&gt;</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 '&lt;&lt;' 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

Comments
 (0)