Sming Framework API
Sming - Open Source framework for high efficiency WiFi SoC ESP8266 native development with C++ language.
HttpHeaders.h
1 /****
2  * Sming Framework Project - Open Source framework for high efficiency native ESP8266 development.
3  * Created 2015 by Skurydin Alexey
4  * http://github.com/SmingHub/Sming
5  * All files of the Sming Core are provided under the LGPL v3 license.
6  *
7  * HttpHeaders.h
8  *
9  * @author: 2018 - Mikee47 <mike@sillyhouse.net>
10  *
11  * Encapsulate encoding and decoding of HTTP header fields
12  * Used for HTTP connections and SMTP mail
13  *
14  * The HttpHeaders class was an empty HashMap class living in 'Structures.h'.
15  * It has been expanded here to simplify code, and to provide enumerated keys
16  * for common field names.
17  *
18  ****/
19 
20 #ifndef _SMING_CORE_NETWORK_HTTP_HTTP_HEADERS_H_
21 #define _SMING_CORE_NETWORK_HTTP_HTTP_HEADERS_H_
22 
23 #include "Data/CStringArray.h"
24 #include "WString.h"
25 #include "WHashMap.h"
26 #include "DateTime.h"
27 
28 /*
29  * Common HTTP header field names. Enumerating these simplifies matching
30  * and generating headers. The strings themselves are stored in flash to
31  * save RAM.
32  *
33  * According to RFC 2616: 4.2, field names are case-insensitive.
34  *
35  * A brief description of each header field is given for information purposes.
36  * For details see https://www.iana.org/assignments/message-headers/message-headers.xhtml
37  *
38  */
39 #define HTTP_HEADER_FIELDNAME_MAP(XX) \
40  XX(ACCESS_CONTROL_ALLOW_ORIGIN, "Access-Control-Allow-Origin", "") \
41  XX(AUTHORIZATION, "Authorization", "Basic user agent authentication") \
42  XX(CC, "Cc", "email field") \
43  XX(CONNECTION, "Connection", "Indicates sender's desired control options") \
44  XX(CONTENT_DISPOSITION, "Content-Disposition", "Additional information about how to process response payload") \
45  XX(CONTENT_ENCODING, "Content-Encoding", "Applied encodings in addition to content type") \
46  XX(CONTENT_LENGTH, "Content-Length", "Anticipated size for payload when not using transfer encoding") \
47  XX(CONTENT_TYPE, "Content-Type", \
48  "Payload media type indicating both data format and intended manner of processing by recipient") \
49  XX(CONTENT_TRANSFER_ENCODING, "Content-Transfer-Encoding", "Coding method used in a MIME message body part") \
50  XX(CACHE_CONTROL, "Cache-Control", "Directives for caches along the request/response chain") \
51  XX(DATE, "Date", "Message originating date/time") \
52  XX(ETAG, "ETag", \
53  "Validates resource, such as a file, so recipient can confirm whether it has changed - generally more " \
54  "reliable than Date") \
55  XX(FROM, "From", "email address of human user who controls the requesting user agent") \
56  XX(HOST, "Host", \
57  "Request host and port information for target URI; allows server to service requests for multiple hosts on a " \
58  "single IP address") \
59  XX(IF_MATCH, "If-Match", \
60  "Precondition check using ETag to avoid accidental overwrites when servicing multiple user requests. Ensures " \
61  "resource entity tag matches before proceeding.") \
62  XX(IF_MODIFIED_SINCE, "If-Modified-Since", "Precondition check using Date") \
63  XX(LAST_MODIFIED, "Last-Modified", "Server timestamp indicating date and time resource was last modified") \
64  XX(LOCATION, "Location", "Used in redirect responses, amongst other places") \
65  XX(SEC_WEBSOCKET_ACCEPT, "Sec-WebSocket-Accept", "Server response to opening Websocket handshake") \
66  XX(SEC_WEBSOCKET_VERSION, "Sec-WebSocket-Version", \
67  "Websocket opening request indicates acceptable protocol version. Can appear more than once.") \
68  XX(SEC_WEBSOCKET_KEY, "Sec-WebSocket-Key", "Websocket opening request validation key") \
69  XX(SEC_WEBSOCKET_PROTOCOL, "Sec-WebSocket-Protocol", \
70  "Websocket opening request indicates supported protocol(s), response contains negotiated protocol(s)") \
71  XX(SERVER, "Server", "Identifies software handling requests") \
72  XX(SET_COOKIE, "Set-Cookie", "Server may pass name/value pairs and associated metadata to user agent (client)") \
73  XX(SUBJECT, "Subject", "email subject line") \
74  XX(TO, "To", "email intended recipient address") \
75  XX(TRANSFER_ENCODING, "Transfer-Encoding", "e.g. Chunked, compress, deflate, gzip") \
76  XX(UPGRADE, "Upgrade", \
77  "Used to transition from HTTP to some other protocol on the same connection. e.g. Websocket") \
78  XX(USER_AGENT, "User-Agent", "Information about the user agent originating the request") \
79  XX(WWW_AUTHENTICATE, "WWW-Authenticate", "Indicates HTTP authentication scheme(s) and applicable parameters")
80 
81 enum HttpHeaderFieldName {
82  HTTP_HEADER_UNKNOWN = 0,
83 #define XX(_tag, _str, _comment) HTTP_HEADER_##_tag,
84  HTTP_HEADER_FIELDNAME_MAP(XX)
85 #undef XX
86  HTTP_HEADER_CUSTOM // First custom header tag value
87 };
88 
96 class HttpHeaders : private HashMap<HttpHeaderFieldName, String>
97 {
98 public:
99  HttpHeaders() = default;
100 
101  HttpHeaders(const HttpHeaders& headers)
102  {
103  *this = headers;
104  }
105 
106  String toString(HttpHeaderFieldName name) const;
107 
113  static String toString(const String& name, const String& value);
114 
115  String toString(HttpHeaderFieldName name, const String& value) const
116  {
117  return toString(toString(name), value);
118  }
119 
125  HttpHeaderFieldName fromString(const String& name) const;
126 
127  using HashMap::operator[];
128 
134  const String& operator[](const String& name) const
135  {
136  auto field = fromString(name);
137  if(field == HTTP_HEADER_UNKNOWN) {
138  return nil;
139  }
140  return operator[](field);
141  }
142 
148  String& operator[](const String& name)
149  {
150  auto field = fromString(name);
151  if(field == HTTP_HEADER_UNKNOWN) {
152  field = static_cast<HttpHeaderFieldName>(HTTP_HEADER_CUSTOM + customFieldNames.count());
153  customFieldNames.add(name);
154  }
155  return operator[](field);
156  }
157 
163  String operator[](unsigned index) const
164  {
165  return toString(keyAt(index), valueAt(index));
166  }
167 
168  using HashMap::contains;
169 
170  bool contains(const String& name) const
171  {
172  return contains(fromString(name));
173  }
174 
175  using HashMap::remove;
176 
177  void remove(const String& name)
178  {
179  remove(fromString(name));
180  }
181 
182  void setMultiple(const HttpHeaders& headers)
183  {
184  for(unsigned i = 0; i < headers.count(); i++) {
185  HttpHeaderFieldName fieldName = headers.keyAt(i);
186  auto fieldNameString = headers.toString(fieldName);
187  operator[](fieldNameString) = headers.valueAt(i);
188  }
189  }
190 
191  HttpHeaders& operator=(const HttpHeaders& headers)
192  {
193  clear();
194  setMultiple(headers);
195  return *this;
196  }
197 
198  void clear()
199  {
200  customFieldNames.clear();
201  HashMap::clear();
202  }
203 
204  using HashMap::count;
205 
206  DateTime getLastModifiedDate() const
207  {
208  DateTime dt;
209  String strLM = operator[](HTTP_HEADER_LAST_MODIFIED);
210  return dt.fromHttpDate(strLM) ? dt : DateTime();
211  }
212 
213  DateTime getServerDate() const
214  {
215  DateTime dt;
216  String strSD = operator[](HTTP_HEADER_DATE);
217  return dt.fromHttpDate(strSD) ? dt : DateTime();
218  }
219 
220 private:
225  HttpHeaderFieldName findCustomFieldName(const String& name) const;
226 
227  CStringArray customFieldNames;
228 };
229 
230 #endif /* _SMING_CORE_NETWORK_HTTP_HTTP_HEADERS_H_ */
unsigned count() const
Get quantity of strings in array.
Date and time class.
Definition: DateTime.h:77
Definition: WHashMap.h:35
void clear()
Empty the array.
Definition: CStringArray.h:109
The string class.
Definition: WString.h:104
String & operator[](const String &name)
Fetch a reference to the header field value by name.
Definition: HttpHeaders.h:148
Encapsulates a set of HTTP header information.
Definition: HttpHeaders.h:96
String operator[](unsigned index) const
Return the HTTP header line for the value at the given index.
Definition: HttpHeaders.h:163
HttpHeaderFieldName fromString(const String &name) const
Find the enumerated value for the given field name string.
#define XX(name, str, port)
Common URI scheme strings.
Definition: Url.h:54
const String & operator[](const String &name) const
Fetch a reference to the header field value by name.
Definition: HttpHeaders.h:134
bool add(const char *str, unsigned length=0)
Append a new string to the end of the array.
Class to manage a double null-terminated list of strings, such as "one\0two\0three".
Definition: CStringArray.h:33
bool fromHttpDate(const String &httpDate)
Parse a HTTP full date and set time and date.