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