xref: /haiku/docs/user/netservices/HttpFields.dox (revision d9a4c6070c64bb1dfdf8b652a9ceebeeed5ce7d4)
1/*
2 * Copyright 2022 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Niels Sascha Reedijk, niels.reedijk@gmail.com
7 *
8 * Corresponds to:
9 *		headers/private/netservices2/HttpFields.h			hrev?????
10 *		src/kits/network/libnetservices2/HttpFields.cpp		hrev?????
11 */
12
13
14#if __cplusplus >= 201703L
15
16
17/*!
18	\file HttpFields.h
19	\ingroup netservices
20	\brief Provides the BHttpFields class.
21*/
22
23namespace BPrivate {
24
25namespace Network {
26
27
28/*!
29	\class BHttpFields
30	\ingroup netservices
31	\brief Represents the field section of a HTTP header.
32
33	The HTTP protocol (RFC 7230) specifies that each HTTP request and response has a header. Part
34	of that header is a list of fields, which are name and value pairs. The high level protocol
35	defines what valid field names and field values look like. When adding or modifying field data,
36	the members of this class enforce those constraints.
37
38	When you are processing a HTTP response, this object gives you the methods to query the headers
39	in that response. When you are creating a HTTP request, this object gives you methods to add
40	and modify header fields on your request. When retrieving data from the header fields, this
41	data is often returned as an \c std::string_view. Please note that this object will only point
42	to valid data for the lifetime of this object, which in case of a HTTP response, will be
43	bound to the lifetime of the object that contains the HTTP response.
44
45	When adding headers, the fields are stored in the order in which they were added. However,
46	when you add additional values with an existing name, the new field will be added below the
47	existing field.
48
49	The HTTP protocol does not prohibit multiple fields with the same name, but it does note that
50	semantically this is only allowed for a limited set of explicitly named headers, like the
51	'Set-Cookie' field (see RFC 7230 section 3.2.2). Because most header fields will only exist
52	once, the interface of this class is optimized for each header field existing only once. The
53	onus is on the user to take additional steps when dealing with header fields that they know
54	can occur more than once.
55
56	\since Haiku R1
57*/
58
59
60/*!
61	\class BHttpFields::InvalidInput
62	\ingroup netservices
63	\brief Error that represents when a string input contains characters that are incompatible with
64		the HTTP specification.
65
66	\since Haiku R1
67*/
68
69
70/*!
71	\var BString BHttpFields::InvalidInput::input
72	\brief The input that contains the invalid contents.
73
74	\since Haiku R1
75*/
76
77
78/*!
79	\fn BHttpFields::InvalidInput::InvalidInput(const char *origin, BString input)
80	\brief Constructor that sets the \a origin and the invalid \a input.
81
82	\since Haiku R1
83*/
84
85
86/*!
87	\fn virtual BString BHttpFields::InvalidInput::DebugMessage() const override
88	\brief Retrieve a debug message that contains all info in this error.
89
90	The output will be along the lines of:
91	\code
92	[Origin] Invalid format or unsupported characters in input    [input]
93	\endcode
94
95	\exception std::bad_alloc In the future this method may throw this
96		exception when the memory for the debug message cannot be allocated.
97
98	\return A \ref BString object that contains the debug message.
99
100	\since Haiku R1
101*/
102
103
104/*!
105	\fn virtual const char* BHttpFields::InvalidInput::Message() const noexcept override
106	\brief Get a pointer to the message describing the error.
107
108	\since Haiku R1
109*/
110
111
112/*!
113	\class BHttpFields::Field
114	\ingroup netservices
115	\brief Represents a HTTP header field.
116
117	This type represents a combination of a field name and a field value. In order to be used in
118	a HTTP header, each object must contain data that is in compliance with the HTTP specification
119	(RFC 7230).
120
121	Some official HTTP specifications give additional guidelines for how to interpret specific
122	fields. This class, however, does not supply any additional parsing for those specializations.
123
124	Manipulation of the contents of a HTTP field will in most cases be done through the interface
125	of the \ref BHttpFields object that owns this field.
126
127	This type has a special 'empty' state. This means that they do not have a key and value. Empty
128	objects only come into existence when explicitly instantiated with the constructor with no
129	arguments, or after the contents has been moved to another object. Empty objects cannot be
130	added to \ref BHttpFields objets. You do not have to check for empty fields when working with
131	fields coming from \ref BHttpFields objects.
132
133	\since Haiku R1
134*/
135
136
137/*!
138	\fn BHttpFields::Field::Field() noexcept
139	\brief Construct empty field.
140
141	This constructs an empty field. Because empty fields cannot be used in combination with a
142	\ref BHttpFields object, it is unlikely that you will construct these empty fields yourself.
143
144	\since Haiku R1
145*/
146
147
148/*!
149	\fn BHttpFields::Field::Field(const std::string_view& name, const std::string_view& value)
150	\brief Construct a field with a \a name and a \a value.
151
152	The parameters are checked whether they only contain characters that are allowed by the HTTP
153	specification.
154
155	\param name The name of the header field.
156	\param value The value of the header field.
157
158	\exception std::bad_alloc Error in case memory cannot be allocated.
159	\exception BHttpFields::InvalidInput This error indicates that the \a name or the \a value
160		is empty or contains invalid characters.
161
162	\since Haiku R1
163*/
164
165
166/*!
167	\fn BHttpFields::Field::Field(const Field &other)
168	\brief Copy constructor.
169
170	\param other The other field to copy data from.
171
172	\exception std::bad_alloc Error in case memory cannot be allocated.
173
174	\since Haiku R1
175*/
176
177
178/*!
179	\fn BHttpFields::Field::Field(Field&& other) noexcept
180	\brief Move constructor.
181
182	After moving, the \a other field object will be an empty field.
183
184	\since Haiku R1
185*/
186
187
188/*!
189	\fn Field& BHttpFields::Field::operator=(const Field &other)
190	\brief Copy assignment.
191
192	\param other The other field to copy data from.
193
194	\exception std::bad_alloc Error in case memory cannot be allocated.
195
196 	\since Haiku R1
197*/
198
199
200/*!
201	\fn Field& BHttpFields::Field::operator=(Field &&other) noexcept
202	\brief Move assignment.
203
204	After moving, the \a other field object will be an empty field.
205
206	\since Haiku R1
207*/
208
209
210/*!
211	\fn const FieldName& BHttpFields::Field::Name() const noexcept
212	\brief Get a const reference to the field name.
213
214	\return The name of the field as a \ref BHttpFields::FieldName.
215
216	\since Haiku R1
217*/
218
219
220/*!
221	\fn std::string_view BHttpFields::Field::Value() const noexcept
222	\brief Get a const reference to the field value.
223
224	\return The contents of the field value as a \a std::string_view.
225
226	\since Haiku R1
227*/
228
229
230/*!
231	\fn bool BHttpFields::Field::IsEmpty() const noexcept
232	\brief Check if the field is empty or has valid data.
233
234	\retval true This field is empty.
235	\retval false This field contains a valid name and value.
236
237	\since Haiku R1
238*/
239
240
241/*!
242	\class BHttpFields::FieldName
243	\ingroup netservices
244	\brief Representation of a HTTP header name.
245
246	As per the HTTP specification, header fields have a name. There are limitations to which
247	characters are supported. As per the specification, header field names are case insensitive.
248	This means that the \c content-encoding is equal to \c Content-Encoding or even
249	\c COnTenT-ENcOdING.
250
251	A header field name can never be empty.
252
253	\since Haiku R1
254*/
255
256
257/*!
258	\fn BHttpFields::FieldName::operator BString() const
259	\brief Return a copy of the header name as a string.
260
261	\return The header name as a \ref BString object.
262
263	\since Haiku R1
264*/
265
266
267/*!
268	\fn BHttpFields::FieldName::operator std::string_view() const
269	\brief Return a \c std::string_view over the header name.
270
271	\return A \c std::string_view object over the header name.
272
273	\since Haiku R1
274*/
275
276
277/*!
278	\fn bool BHttpFields::FieldName::operator==(const BString &other) const noexcept
279	\brief Compare the header name to a string.
280
281	\param other The \c other string to compare it to.
282
283	The comparison is case-insensitive. So if this header name is set to \c Content-Encoding,
284	comparing it to \c content-encoding will return \c true.
285
286	\retval true The current header name is equal to the \a other name.
287	\retval false The current header name is different from the \a other name.
288
289	\since Haiku R1
290*/
291
292
293/*!
294	\fn bool BHttpFields::FieldName::operator==(const std::string_view& other) const noexcept
295	\copydoc BHttpFields::FieldName::operator==(const BString &other) const noexcept
296*/
297
298
299/*!
300	\fn bool BHttpFields::FieldName::operator==(const BHttpFields::FieldName& other) const noexcept
301	\copydoc BHttpFields::FieldName::operator==(const BString &other) const noexcept
302*/
303
304
305/*!
306	\typedef BHttpFields::ConstIterator
307	\brief Define a constant iterator to iterate through the list of header fields.
308
309	This iterator has the same semantics as other constant iterators in the C++ standard library.
310
311	\since Haiku R1
312*/
313
314
315/*!
316	\name Constructors & Destructor
317*/
318
319
320//! @{
321
322
323/*!
324	\fn BHttpFields::BHttpFields()
325	\brief Construct an empty list of HTTP header fields.
326
327	\exception std::bad_alloc Error in case memory cannot be allocated.
328
329	\since Haiku R1
330*/
331
332
333/*!
334	\fn BHttpFields::BHttpFields(std::initializer_list< Field > fields)
335	\brief Initialize the object with a list of fields.
336
337	This enables you to initialize the fields with a list of \ref BHttpFields::Field objects. Any
338	empty fields will be skipped. Like \ref AddField(), this constructor keeps the fields in the
339	original order, though duplicate keys will be grouped together in sequence.
340
341	The example below will create an object with four fields, even though five fields have been
342	passed in the initializer. The last header will be reorderd to follow the other
343	\c Accept-Encoding header.
344	\code
345	const BHttpFields defaultFields = {
346		{"Host"sv, "haiku-os.org"sv},
347		{"Accept-Encoding"sv, "gzip"sv}
348		{"Accept"sv, "*\/*"sv},
349		{},
350		{"Accept-Encoding"sv, "bzip2"sv}
351	};
352	\endcode
353
354	\exception std::bad_alloc Error in case memory cannot be allocated.
355	\exception BHttpFields::InvalidInput This error indicates that some of the names or values in
356		the list do not adhere to the HTTP specification.
357
358	\since Haiku R1
359*/
360
361
362/*!
363	\fn BHttpFields::BHttpFields(const BHttpFields &other)
364	\brief Copy constructor.
365
366	\exception std::bad_alloc Error in case memory cannot be allocated.
367
368	\since Haiku R1
369*/
370
371
372/*!
373	\fn BHttpFields::BHttpFields(BHttpFields &&other)
374	\brief Move constructor.
375
376	The name and value from the \a other fields object will be moved to this object. The \a other
377	object will be empty, meaning it no longer has any fields.
378
379	\exception std::bad_alloc Error in case memory cannot be allocated.
380
381	\since Haiku R1
382*/
383
384
385/*!
386	\fn BHttpFields::~BHttpFields() noexcept
387	\brief Destructor.
388
389	\since Haiku R1
390*/
391
392
393//! @}
394
395
396/*!
397	\name Assignment operators
398*/
399
400
401//! @{
402
403
404/*!
405	\fn BHttpFields& BHttpFields::operator=(BHttpFields &&other) noexcept
406	\brief Move assignment operator.
407
408	The name and value from the \a other fields object will be moved to this object. The \a other
409	object will be empty, meaning it no longer has any fields.
410
411	\since Haiku R1
412*/
413
414
415/*!
416	\fn BHttpFields& BHttpFields::operator=(const BHttpFields &other)
417	\brief Copy assignment operator.
418
419	Make a new fields object with a copy of the fields of the \a other header.
420
421	\exception std::bad_alloc Error in case memory cannot be allocated.
422
423	\since Haiku R1
424*/
425
426
427//! @}
428
429
430/*!
431	\name List Access
432*/
433
434
435//! @{
436
437/*!
438	\fn const Field& BHttpFields::operator[](size_t index) const
439	\brief Get the item at an \a index.
440
441	\param index The zero-based index of the item in the list of fields.
442
443	\return A const reference to the the field.
444
445	\exception BRuntimeError Error in case the index is out of bounds.
446
447	\since Haiku R1
448*/
449
450
451//! @}
452
453
454/*!
455	\name Modifying the list
456*/
457
458
459//! @{
460
461/*!
462	\fn void BHttpFields::AddField(const std::string_view &name, const std::string_view &value)
463	\brief Append a field with \a name and a \a value to the list of headers.
464
465	The parameters are checked whether they only contain characters that are allowed by the HTTP
466	specification.
467
468	\param name The name of the header field.
469	\param value The value of the header field.
470
471	\exception std::bad_alloc Error in case memory cannot be allocated.
472	\exception BHttpFields::InvalidInput This error indicates that the \a name or the \a value
473		contains invalid characters.
474
475	\since Haiku R1
476*/
477
478
479/*!
480	\fn void BHttpFields::AddFields(std::initializer_list< Field > fields)
481	\brief Add a list of fields.
482
483	This enables you to add a list of \ref BHttpFields::Field objects. Like \ref AddField(), the
484	fields are added in the the original order, though if there are duplicate keys within the
485	\a fields list, or there are existing keys in the object, they will be grouped together in
486	sequence.
487
488	\exception std::bad_alloc Error in case memory cannot be allocated.
489	\exception BHttpFields::InvalidInput This error indicates that some of the names or values in
490		the list do not adhere to the HTTP specification.
491
492	\since Haiku R1
493*/
494
495
496/*!
497	\fn void BHttpFields::RemoveField(const std::string_view &name) noexcept
498	\brief Remove all fields with the \a name.
499
500	If there are no fields with this name, this method does nothing. Like all operations that
501	involve a field name, the name matching is case insensitive.
502
503	\param name The name of the field to remove.
504
505	\since Haiku R1
506*/
507
508
509/*!
510	\fn void BHttpFields::RemoveField(ConstIterator it) noexcept
511	\brief Remove the specific field at the location of an iterator.
512
513	\param it A valid iterator to the item that must be removed.
514
515	\since Haiku R1
516*/
517
518
519/*!
520	\fn void BHttpFields::MakeEmpty() noexcept
521	\brief Clear all fields from this header.
522
523	Removes all fields from the container.
524
525	\since Haiku R1
526*/
527
528
529//! @}
530
531
532/*!
533	\name Querying
534*/
535
536
537//! @{
538
539
540/*!
541	\fn ConstIterator BHttpFields::FindField(const std::string_view &name) const noexcept
542	\brief Find a field with \a name.
543
544	In case there are more than one fields with the same name, this container will make sure that
545	these are grouped together. That means that you can use the properties of the iterator to find
546	the other fields.
547
548	\param name The name of the field to be found.
549
550	\return Returns a valid iterator to the first field with \a name in this container, or
551		BHttpFields::end() in case the name is not found.
552
553	\since Haiku R1
554*/
555
556
557/*!
558	\fn size_t BHttpFields::CountFields() const noexcept
559	\brief Get the number of fields.
560
561	\return The number of fields in this container. If multiple fields have the same name, they
562		will be counted individually.
563
564	\since Haiku R1
565*/
566
567
568//! @}
569
570
571/*!
572	\name Range-based iteration.
573	Allows the usage of this object in a for loop.
574*/
575
576
577//! @{
578
579/*!
580	\fn ConstIterator BHttpFields::begin() const noexcept
581	\brief Return an iterator to the first field.
582
583	\since Haiku R1
584*/
585
586
587/*!
588	\fn ConstIterator BHttpFields::end() const noexcept
589	\brief Return an iterator to the end of the fields.
590
591	\since Haiku R1
592*/
593
594
595//! @}
596
597
598} // namespace Network
599
600} // namespace BPrivate
601
602#endif
603