Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/boostorg/url
9 : //
10 :
11 : #ifndef BOOST_URL_URL_BASE_HPP
12 : #define BOOST_URL_URL_BASE_HPP
13 :
14 : #include <boost/url/detail/config.hpp>
15 : #include <boost/url/ipv4_address.hpp>
16 : #include <boost/url/ipv6_address.hpp>
17 : #include <boost/url/params_encoded_ref.hpp>
18 : #include <boost/url/params_ref.hpp>
19 : #include <boost/url/pct_string_view.hpp>
20 : #include <boost/url/scheme.hpp>
21 : #include <boost/url/segments_encoded_ref.hpp>
22 : #include <boost/url/segments_ref.hpp>
23 : #include <boost/url/url_view_base.hpp>
24 : #include <cstdint>
25 : #include <initializer_list>
26 : #include <memory>
27 : #include <string>
28 : #include <utility>
29 :
30 : namespace boost {
31 : namespace urls {
32 :
33 : namespace detail {
34 : struct any_params_iter;
35 : struct any_segments_iter;
36 : struct params_iter_impl;
37 : struct segments_iter_impl;
38 : struct pattern;
39 : }
40 :
41 : /** Common functionality for containers
42 :
43 : This base class is used by the library
44 : to provide common member functions for
45 : containers. This cannot be instantiated
46 : directly; Instead, use one of the
47 : containers or functions:
48 :
49 : @par Containers
50 : @li @ref url
51 : @li @ref url_view
52 : @li @ref static_url
53 :
54 : @par Functions
55 : @li @ref parse_absolute_uri
56 : @li @ref parse_origin_form
57 : @li @ref parse_relative_ref
58 : @li @ref parse_uri
59 : @li @ref parse_uri_reference
60 : */
61 : class url_base
62 : : public url_view_base
63 : {
64 : char* s_ = nullptr;
65 : std::size_t cap_ = 0;
66 :
67 : friend class url;
68 : friend class static_url_base;
69 : friend class params_ref;
70 : friend class segments_ref;
71 : friend class segments_encoded_ref;
72 : friend class params_encoded_ref;
73 : friend struct detail::pattern;
74 :
75 : struct op_t
76 : {
77 : ~op_t();
78 : op_t(url_base&,
79 : core::string_view* = nullptr,
80 : core::string_view* = nullptr) noexcept;
81 : void move(char*, char const*,
82 : std::size_t) noexcept;
83 :
84 : url_base& u;
85 : core::string_view* s0 = nullptr;
86 : core::string_view* s1 = nullptr;
87 : char* old = nullptr;
88 : };
89 :
90 5648 : virtual ~url_base() noexcept = default;
91 4145 : url_base() noexcept = default;
92 : url_base(detail::url_impl const&) noexcept;
93 : explicit url_base(core::string_view);
94 : void reserve_impl(std::size_t n);
95 : void copy(url_view_base const&);
96 : virtual void clear_impl() noexcept = 0;
97 : virtual void reserve_impl(
98 : std::size_t, op_t&) = 0;
99 : virtual void cleanup(op_t&) = 0;
100 :
101 : public:
102 : //--------------------------------------------
103 : //
104 : // Observers
105 : //
106 : //--------------------------------------------
107 :
108 : /** Return the url as a null-terminated string
109 :
110 : This function returns a pointer to a null
111 : terminated string representing the url,
112 : which may contain percent escapes.
113 :
114 : @return A pointer to a null-terminated string containing the URL.
115 :
116 : @par Example
117 : @code
118 : assert( std::strlen( url( "http://www.example.com" ).c_str() ) == 22 );
119 : @endcode
120 :
121 : @par Complexity
122 : Constant.
123 :
124 : @par Exception Safety
125 : Throws nothing.
126 : */
127 : char const*
128 18357 : c_str() const noexcept
129 : {
130 18357 : return impl().cs_;
131 : }
132 :
133 : /** Return the number of characters that can be stored without reallocating
134 :
135 : This does not include the null terminator,
136 : which is always present.
137 :
138 : @return `*this`
139 :
140 : @par Complexity
141 : Constant.
142 :
143 : @par Exception Safety
144 : Throws nothing.
145 : */
146 : std::size_t
147 10 : capacity() const noexcept
148 : {
149 10 : return cap_;
150 : }
151 :
152 : /** Clear the contents while preserving the capacity
153 :
154 : @par Postconditions
155 : @code
156 : this->empty() == true
157 : @endcode
158 :
159 : @par Complexity
160 : Constant.
161 :
162 : @par Exception Safety
163 : No-throw guarantee.
164 : */
165 : void
166 120 : clear() noexcept
167 : {
168 120 : this->clear_impl();
169 120 : }
170 :
171 : /** Adjust the capacity without changing the size
172 :
173 : This function adjusts the capacity
174 : of the container in characters, without
175 : affecting the current contents. Has
176 : no effect if `n <= this->capacity()`.
177 :
178 : @par Exception Safety
179 : Strong guarantee.
180 : Calls to allocate may throw.
181 :
182 : @throw bad_alloc Allocation failure
183 :
184 : @param n The capacity in characters,
185 : excluding any null terminator.
186 : */
187 : void
188 165 : reserve(std::size_t n)
189 : {
190 165 : reserve_impl(n);
191 164 : }
192 :
193 : //--------------------------------------------
194 : //
195 : // Fluent API
196 : //
197 :
198 : //--------------------------------------------
199 : //
200 : // Scheme
201 : //
202 : //--------------------------------------------
203 :
204 : /** Set the scheme
205 :
206 : The scheme is set to the specified
207 : string, which must contain a valid
208 : scheme without any trailing colon
209 : (':').
210 : Note that schemes are case-insensitive,
211 : and the canonical form is lowercased.
212 :
213 : @par Example
214 : @code
215 : assert( url( "http://www.example.com" ).set_scheme( "https" ).scheme_id() == scheme::https );
216 : @endcode
217 :
218 : @par Complexity
219 : Linear in `this->size() + s.size()`.
220 :
221 : @par Exception Safety
222 : Strong guarantee.
223 : Calls to allocate may throw.
224 : Exceptions thrown on invalid input.
225 :
226 : @throw system_error
227 : `s` contains an invalid scheme.
228 :
229 : @param s The scheme to set.
230 :
231 : @return `*this`
232 :
233 : @par BNF
234 : @code
235 : scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
236 : @endcode
237 :
238 : @par Specification
239 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
240 : 3.1. Scheme (rfc3986)</a>
241 :
242 : @see
243 : @ref remove_scheme.
244 : */
245 : url_base&
246 : set_scheme(core::string_view s);
247 :
248 : /** Set the scheme
249 :
250 : This function sets the scheme to the specified
251 : known @ref urls::scheme id, which may not be
252 : @ref scheme::unknown or else an exception is
253 : thrown. If the id is @ref scheme::none, this
254 : function behaves as if @ref remove_scheme
255 : were called.
256 :
257 : @par Example
258 : @code
259 : assert( url( "http://example.com/echo.cgi" ).set_scheme_id( scheme::wss ).buffer() == "wss://example.com/echo.cgi" );
260 : @endcode
261 :
262 : @par Complexity
263 : Linear in `this->size()`.
264 :
265 : @par Exception Safety
266 : Strong guarantee.
267 : Calls to allocate may throw.
268 : Exceptions thrown on invalid input.
269 :
270 : @throw system_error
271 : The scheme is invalid.
272 :
273 : @param id The scheme to set.
274 : @return `*this`
275 :
276 : @par Specification
277 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
278 : 3.1. Scheme (rfc3986)</a>
279 : */
280 : url_base&
281 : set_scheme_id(urls::scheme id);
282 :
283 : /** Remove the scheme
284 :
285 : This function removes the scheme if it
286 : is present.
287 :
288 : @par Example
289 : @code
290 : assert( url("http://www.example.com/index.htm" ).remove_scheme().buffer() == "//www.example.com/index.htm" );
291 : @endcode
292 :
293 : @par Postconditions
294 : @code
295 : this->has_scheme() == false && this->scheme_id() == scheme::none
296 : @endcode
297 :
298 : @par Complexity
299 : Linear in `this->size()`.
300 :
301 : @par Exception Safety
302 : Throws nothing.
303 :
304 : @return `*this`
305 :
306 : @par BNF
307 : @code
308 : URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
309 : @endcode
310 :
311 : @par Specification
312 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.1">
313 : 3.1. Scheme (rfc3986)</a>
314 :
315 : @see
316 : @ref set_scheme.
317 : */
318 : url_base&
319 : remove_scheme();
320 :
321 : //--------------------------------------------
322 : //
323 : // Authority
324 : //
325 : //--------------------------------------------
326 :
327 : /** Set the authority
328 :
329 : This function sets the authority
330 : to the specified string.
331 : The string may contain percent-escapes.
332 :
333 : @par Example
334 : @code
335 : assert( url().set_encoded_authority( "My%20Computer" ).has_authority() );
336 : @endcode
337 :
338 : @par Exception Safety
339 : Strong guarantee.
340 : Calls to allocate may throw.
341 : Exceptions thrown on invalid input.
342 :
343 : @throw system_eror
344 : The string contains an invalid percent-encoding.
345 :
346 : @param s The authority string to set.
347 : @return `*this`
348 :
349 : @par BNF
350 : @code
351 : authority = [ userinfo "@" ] host [ ":" port ]
352 :
353 : userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
354 : host = IP-literal / IPv4address / reg-name
355 : port = *DIGIT
356 : @endcode
357 :
358 : @par Specification
359 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2">
360 : 3.2. Authority (rfc3986)</a>
361 : @see
362 : @ref remove_authority.
363 : */
364 : url_base&
365 : set_encoded_authority(
366 : pct_string_view s);
367 :
368 : /** Remove the authority
369 :
370 : This function removes the authority,
371 : which includes the userinfo, host, and
372 : a port if present.
373 :
374 : @par Example
375 : @code
376 : assert( url( "http://example.com/echo.cgi" ).remove_authority().buffer() == "http:/echo.cgi" );
377 : @endcode
378 :
379 : @par Postconditions
380 : @code
381 : this->has_authority() == false && this->has_userinfo() == false && this->has_port() == false
382 : @endcode
383 :
384 : @par Complexity
385 : Linear in `this->size()`.
386 :
387 : @par Exception Safety
388 : Throws nothing.
389 :
390 : @return `*this`
391 :
392 : @par BNF
393 : @code
394 : authority = [ userinfo "@" ] host [ ":" port ]
395 :
396 : userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
397 : host = IP-literal / IPv4address / reg-name
398 : port = *DIGIT
399 : @endcode
400 :
401 : @par Specification
402 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2">
403 : 3.2. Authority (rfc3986)</a>
404 :
405 : @see
406 : @ref set_encoded_authority.
407 : */
408 : url_base&
409 : remove_authority();
410 :
411 : //--------------------------------------------
412 : //
413 : // Userinfo
414 : //
415 : //--------------------------------------------
416 :
417 : /** Set the userinfo
418 :
419 : The userinfo is set to the given string,
420 : which may contain percent-escapes.
421 : Any special or reserved characters in the
422 : string are automatically percent-encoded.
423 : The effects on the user and password
424 : depend on the presence of a colon (':')
425 : in the string:
426 :
427 : @li If an unescaped colon exists, the
428 : characters up to the colon become
429 : the user and the rest of the characters
430 : after the colon become the password.
431 : In this case @ref has_password returns
432 : true. Otherwise,
433 :
434 : @li If there is no colon, the user is
435 : set to the string. The function
436 : @ref has_password returns false.
437 :
438 : @note
439 : The interpretation of the userinfo as
440 : individual user and password components
441 : is scheme-dependent. Transmitting
442 : passwords in URLs is deprecated.
443 :
444 : @par Example
445 : @code
446 : assert( url( "http://example.com" ).set_userinfo( "user:pass" ).encoded_user() == "user" );
447 : @endcode
448 :
449 : @par Complexity
450 : Linear in `this->size() + s.size()`.
451 :
452 : @par Exception Safety
453 : Strong guarantee.
454 : Calls to allocate may throw.
455 :
456 : @param s The string to set.
457 : @return `*this`
458 :
459 : @par BNF
460 : @code
461 : userinfo = [ [ user ] [ ':' password ] ]
462 :
463 : user = *( unreserved / pct-encoded / sub-delims )
464 : password = *( unreserved / pct-encoded / sub-delims / ":" )
465 : @endcode
466 :
467 : @par Specification
468 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
469 : 3.2.1. User Information (rfc3986)</a>
470 :
471 : @see
472 : @ref remove_userinfo,
473 : @ref set_encoded_userinfo.
474 : */
475 : url_base&
476 : set_userinfo(
477 : core::string_view s);
478 :
479 : /** Set the userinfo.
480 :
481 : The userinfo is set to the given string,
482 : which may contain percent-escapes.
483 : Escapes in the string are preserved,
484 : and reserved characters in the string
485 : are percent-escaped in the result.
486 : The effects on the user and password
487 : depend on the presence of a colon (':')
488 : in the string:
489 :
490 : @li If an unescaped colon exists, the
491 : characters up to the colon become
492 : the user and the rest of the characters
493 : after the colon become the password.
494 : In this case @ref has_password returns
495 : true. Otherwise,
496 :
497 : @li If there is no colon, the user is
498 : set to the string. The function
499 : @ref has_password returns false.
500 :
501 : @note
502 : The interpretation of the userinfo as
503 : individual user and password components
504 : is scheme-dependent. Transmitting
505 : passwords in URLs is deprecated.
506 :
507 : @par Example
508 : @code
509 : assert( url( "http://example.com" ).set_encoded_userinfo( "john%20doe" ).user() == "john doe" );
510 : @endcode
511 :
512 : @par Complexity
513 : Linear in `this->size() + s.size()`.
514 :
515 : @par Exception Safety
516 : Strong guarantee.
517 : Calls to allocate may throw.
518 : Exceptions thrown on invalid input.
519 :
520 : @throw system_error
521 : `s` contains an invalid percent-encoding.
522 :
523 : @param s The string to set.
524 : @return `*this`
525 :
526 : @par BNF
527 : @code
528 : userinfo = [ [ user ] [ ':' password ] ]
529 :
530 : user = *( unreserved / pct-encoded / sub-delims )
531 : password = *( unreserved / pct-encoded / sub-delims / ":" )
532 : @endcode
533 :
534 : @par Specification
535 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
536 : 3.2.1. User Information (rfc3986)</a>
537 :
538 : @see
539 : @ref remove_userinfo,
540 : @ref set_userinfo.
541 : */
542 : url_base&
543 : set_encoded_userinfo(
544 : pct_string_view s);
545 :
546 : /** Remove the userinfo
547 :
548 : This function removes the userinfo if
549 : present, without removing any authority.
550 :
551 : @par Example
552 : @code
553 : assert( url( "http://user@example.com" ).remove_userinfo().has_userinfo() == false );
554 : @endcode
555 :
556 : @par Postconditions
557 : @code
558 : this->has_userinfo() == false && this->encoded_userinfo().empty == true
559 : @endcode
560 :
561 : @par Complexity
562 : Linear in `this->size()`.
563 :
564 : @par Exception Safety
565 : Throws nothing.
566 :
567 : @return `*this`
568 :
569 : @par BNF
570 : @code
571 : userinfo = [ [ user ] [ ':' password ] ]
572 :
573 : user = *( unreserved / pct-encoded / sub-delims )
574 : password = *( unreserved / pct-encoded / sub-delims / ":" )
575 : @endcode
576 :
577 : @par Specification
578 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
579 : 3.2.1. User Information (rfc3986)</a>
580 :
581 : @see
582 : @ref set_encoded_userinfo,
583 : @ref set_userinfo.
584 : */
585 : url_base&
586 : remove_userinfo() noexcept;
587 :
588 : //--------------------------------------------
589 :
590 : /** Set the user
591 :
592 : This function sets the user part of the
593 : userinfo to the string.
594 : Any special or reserved characters in the
595 : string are automatically percent-encoded.
596 :
597 : @par Example
598 : @code
599 : assert( url().set_user("john doe").encoded_userinfo() == "john%20doe" );
600 : @endcode
601 :
602 : @par Postconditions
603 : @code
604 : this->has_authority() == true && this->has_userinfo() == true
605 : @endcode
606 :
607 : @par Complexity
608 : Linear in `this->size() + s.size()`.
609 :
610 : @par Exception Safety
611 : Strong guarantee.
612 : Calls to allocate may throw.
613 :
614 : @param s The string to set.
615 : @return `*this`
616 :
617 : @par BNF
618 : @code
619 : userinfo = [ [ user ] [ ':' password ] ]
620 :
621 : user = *( unreserved / pct-encoded / sub-delims )
622 : password = *( unreserved / pct-encoded / sub-delims / ":" )
623 : @endcode
624 :
625 : @par Specification
626 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
627 : 3.2.1. User Information (rfc3986)</a>
628 :
629 : @see
630 : @ref remove_password,
631 : @ref set_encoded_password,
632 : @ref set_encoded_user,
633 : @ref set_password.
634 : */
635 : url_base&
636 : set_user(
637 : core::string_view s);
638 :
639 : /** Set the user
640 :
641 : This function sets the user part of the
642 : userinfo the the string, which may
643 : contain percent-escapes.
644 : Escapes in the string are preserved,
645 : and reserved characters in the string
646 : are percent-escaped in the result.
647 :
648 : @par Example
649 : @code
650 : assert( url().set_encoded_user("john%20doe").userinfo() == "john doe" );
651 : @endcode
652 :
653 : @par Postconditions
654 : @code
655 : this->has_authority() == true && this->has_userinfo() == true
656 : @endcode
657 :
658 : @par Complexity
659 : Linear in `this->size() + s.size()`.
660 :
661 : @par Exception Safety
662 : Strong guarantee.
663 : Calls to allocate may throw.
664 :
665 : @throw system_error
666 : `s` contains an invalid percent-encoding.
667 :
668 : @param s The string to set.
669 :
670 : @return `*this`
671 :
672 : @return `*this`
673 :
674 : @par BNF
675 : @code
676 : userinfo = [ [ user ] [ ':' password ] ]
677 :
678 : user = *( unreserved / pct-encoded / sub-delims )
679 : password = *( unreserved / pct-encoded / sub-delims / ":" )
680 : @endcode
681 :
682 : @par Specification
683 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
684 : 3.2.1. User Information (rfc3986)</a>
685 :
686 : @see
687 : @ref remove_password,
688 : @ref set_encoded_password,
689 : @ref set_password,
690 : @ref set_user.
691 : */
692 : url_base&
693 : set_encoded_user(
694 : pct_string_view s);
695 :
696 : /** Set the password.
697 :
698 : This function sets the password in
699 : the userinfo to the string.
700 : Reserved characters in the string are
701 : percent-escaped in the result.
702 :
703 : @note
704 : The interpretation of the userinfo as
705 : individual user and password components
706 : is scheme-dependent. Transmitting
707 : passwords in URLs is deprecated.
708 :
709 : @par Example
710 : @code
711 : assert( url("http://user@example.com").set_password( "pass" ).encoded_userinfo() == "user:pass" );
712 : @endcode
713 :
714 : @par Postconditions
715 : @code
716 : this->has_password() == true && this->password() == s
717 : @endcode
718 :
719 : @par Exception Safety
720 : Strong guarantee.
721 : Calls to allocate may throw.
722 :
723 : @param s The string to set. This string may
724 : contain any characters, including nulls.
725 :
726 : @return `*this`
727 :
728 : @par BNF
729 : @code
730 : userinfo = [ [ user ] [ ':' password ] ]
731 :
732 : user = *( unreserved / pct-encoded / sub-delims )
733 : password = *( unreserved / pct-encoded / sub-delims / ":" )
734 : @endcode
735 :
736 : @par Specification
737 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
738 : 3.2.1. User Information (rfc3986)</a>
739 :
740 : @see
741 : @ref remove_password,
742 : @ref set_encoded_password,
743 : @ref set_encoded_user,
744 : @ref set_user.
745 : */
746 : url_base&
747 : set_password(
748 : core::string_view s);
749 :
750 : /** Set the password.
751 :
752 : This function sets the password in
753 : the userinfo to the string, which
754 : may contain percent-escapes.
755 : Escapes in the string are preserved,
756 : and reserved characters in the string
757 : are percent-escaped in the result.
758 :
759 : @note
760 : The interpretation of the userinfo as
761 : individual user and password components
762 : is scheme-dependent. Transmitting
763 : passwords in URLs is deprecated.
764 :
765 : @par Example
766 : @code
767 : assert( url("http://user@example.com").set_encoded_password( "pass" ).encoded_userinfo() == "user:pass" );
768 : @endcode
769 :
770 : @par Postconditions
771 : @code
772 : this->has_password() == true
773 : @endcode
774 :
775 : @par Exception Safety
776 : Strong guarantee.
777 : Calls to allocate may throw.
778 :
779 : @throw system_error
780 : `s` contains an invalid percent-encoding.
781 :
782 : @param s The string to set. This string may
783 : contain any characters, including nulls.
784 : @return `*this`
785 :
786 : @par BNF
787 : @code
788 : userinfo = [ [ user ] [ ':' password ] ]
789 :
790 : user = *( unreserved / pct-encoded / sub-delims )
791 : password = *( unreserved / pct-encoded / sub-delims / ":" )
792 : @endcode
793 :
794 : @par Specification
795 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
796 : 3.2.1. User Information (rfc3986)</a>
797 :
798 : @see
799 : @ref remove_password,
800 : @ref set_encoded_password,
801 : @ref set_encoded_user,
802 : @ref set_user.
803 : */
804 : url_base&
805 : set_encoded_password(
806 : pct_string_view s);
807 :
808 : /** Remove the password
809 :
810 : This function removes the password from
811 : the userinfo if a password exists. If
812 : there is no userinfo or no authority,
813 : the call has no effect.
814 :
815 : @note
816 : The interpretation of the userinfo as
817 : individual user and password components
818 : is scheme-dependent. Transmitting
819 : passwords in URLs is deprecated.
820 :
821 : @par Example
822 : @code
823 : assert( url( "http://user:pass@example.com" ).remove_password().authority().buffer() == "user@example.com" );
824 : @endcode
825 :
826 : @par Postconditions
827 : @code
828 : this->has_password() == false && this->encoded_password().empty() == true
829 : @endcode
830 :
831 : @par Complexity
832 : Linear in `this->size()`.
833 :
834 : @par Exception Safety
835 : Throws nothing.
836 :
837 : @par BNF
838 : @code
839 : userinfo = [ [ user ] [ ':' password ] ]
840 :
841 : user = *( unreserved / pct-encoded / sub-delims )
842 : password = *( unreserved / pct-encoded / sub-delims / ":" )
843 : @endcode
844 :
845 : @return `*this`
846 :
847 : @par Specification
848 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.1">
849 : 3.2.1. User Information (rfc3986)</a>
850 :
851 : @see
852 : @ref set_encoded_password,
853 : @ref set_encoded_user,
854 : @ref set_password,
855 : @ref set_user.
856 : */
857 : url_base&
858 : remove_password() noexcept;
859 :
860 : //--------------------------------------------
861 : //
862 : // Host
863 : //
864 : //--------------------------------------------
865 :
866 : /** Set the host
867 :
868 : Depending on the contents of the passed
869 : string, this function sets the host:
870 :
871 : @li If the string is a valid IPv4 address,
872 : then the host is set to the address.
873 : The host type is @ref host_type::ipv4.
874 :
875 : @li If the string is a valid IPv6 address
876 : enclosed in square brackets, then the
877 : host is set to that address.
878 : The host type is @ref host_type::ipv6.
879 :
880 : @li If the string is a valid IPvFuture
881 : address enclosed in square brackets, then
882 : the host is set to that address.
883 : The host type is @ref host_type::ipvfuture.
884 :
885 : @li Otherwise, the host name is set to
886 : the string, which may be empty.
887 : Reserved characters in the string are
888 : percent-escaped in the result.
889 : The host type is @ref host_type::name.
890 :
891 : In all cases, when this function returns,
892 : the URL contains an authority.
893 :
894 : @par Example
895 : @code
896 : assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
897 : @endcode
898 :
899 : @par Postconditions
900 : @code
901 : this->has_authority() == true
902 : @endcode
903 :
904 : @par Complexity
905 : Linear in `this->size() + s.size()`.
906 :
907 : @par Exception Safety
908 : Strong guarantee.
909 : Calls to allocate may throw.
910 :
911 : @par BNF
912 : @code
913 : host = IP-literal / IPv4address / reg-name
914 :
915 : IP-literal = "[" ( IPv6address / IPvFuture ) "]"
916 :
917 : reg-name = *( unreserved / pct-encoded / "-" / ".")
918 : @endcode
919 :
920 : @param s The string to set.
921 : @return `*this`
922 :
923 : @par Specification
924 : @li <a href="https://en.wikipedia.org/wiki/IPv4"
925 : >IPv4 (Wikipedia)</a>
926 : @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
927 : >IP Version 6 Addressing Architecture (rfc4291)</a>
928 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
929 : 3.2.2. Host (rfc3986)</a>
930 :
931 : @see
932 : @ref set_encoded_host,
933 : @ref set_encoded_host_address,
934 : @ref set_encoded_host_name,
935 : @ref set_host_address,
936 : @ref set_host_ipv4,
937 : @ref set_host_ipv6,
938 : @ref set_host_ipvfuture,
939 : @ref set_host_name.
940 : */
941 : url_base&
942 : set_host(
943 : core::string_view s);
944 :
945 : /** Set the host
946 :
947 : Depending on the contents of the passed
948 : string, this function sets the host:
949 :
950 : @li If the string is a valid IPv4 address,
951 : then the host is set to the address.
952 : The host type is @ref host_type::ipv4.
953 :
954 : @li If the string is a valid IPv6 address
955 : enclosed in square brackets, then the
956 : host is set to that address.
957 : The host type is @ref host_type::ipv6.
958 :
959 : @li If the string is a valid IPvFuture
960 : address enclosed in square brackets, then
961 : the host is set to that address.
962 : The host type is @ref host_type::ipvfuture.
963 :
964 : @li Otherwise, the host name is set to
965 : the string. This string can contain percent
966 : escapes, or can be empty.
967 : Escapes in the string are preserved,
968 : and reserved characters in the string
969 : are percent-escaped in the result.
970 : The host type is @ref host_type::name.
971 :
972 : In all cases, when this function returns,
973 : the URL contains an authority.
974 :
975 : @par Example
976 : @code
977 : assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
978 : @endcode
979 :
980 : @par Postconditions
981 : @code
982 : this->has_authority() == true
983 : @endcode
984 :
985 : @par Complexity
986 : Linear in `this->size() + s.size()`.
987 :
988 : @par Exception Safety
989 : Strong guarantee.
990 : Calls to allocate may throw.
991 : Exceptions thrown on invalid input.
992 :
993 : @throw system_error
994 : `s` contains an invalid percent-encoding.
995 :
996 : @param s The string to set.
997 :
998 : @return `*this`
999 :
1000 : @par BNF
1001 : @code
1002 : host = IP-literal / IPv4address / reg-name
1003 :
1004 : IP-literal = "[" ( IPv6address / IPvFuture ) "]"
1005 :
1006 : reg-name = *( unreserved / pct-encoded / "-" / ".")
1007 : @endcode
1008 :
1009 : @par Specification
1010 : @li <a href="https://en.wikipedia.org/wiki/IPv4"
1011 : >IPv4 (Wikipedia)</a>
1012 : @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
1013 : >IP Version 6 Addressing Architecture (rfc4291)</a>
1014 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1015 : 3.2.2. Host (rfc3986)</a>
1016 :
1017 : @see
1018 : @ref set_encoded_host_address,
1019 : @ref set_encoded_host_name,
1020 : @ref set_host,
1021 : @ref set_host_address,
1022 : @ref set_host_ipv4,
1023 : @ref set_host_ipv6,
1024 : @ref set_host_ipvfuture,
1025 : @ref set_host_name.
1026 : */
1027 : url_base&
1028 : set_encoded_host(pct_string_view s);
1029 :
1030 : /** Set the host to an address
1031 :
1032 : Depending on the contents of the passed
1033 : string, this function sets the host:
1034 :
1035 : @li If the string is a valid IPv4 address,
1036 : then the host is set to the address.
1037 : The host type is @ref host_type::ipv4.
1038 :
1039 : @li If the string is a valid IPv6 address,
1040 : then the host is set to that address.
1041 : The host type is @ref host_type::ipv6.
1042 :
1043 : @li If the string is a valid IPvFuture,
1044 : then the host is set to that address.
1045 : The host type is @ref host_type::ipvfuture.
1046 :
1047 : @li Otherwise, the host name is set to
1048 : the string, which may be empty.
1049 : Reserved characters in the string are
1050 : percent-escaped in the result.
1051 : The host type is @ref host_type::name.
1052 :
1053 : In all cases, when this function returns,
1054 : the URL contains an authority.
1055 :
1056 : @par Example
1057 : @code
1058 : assert( url( "http://www.example.com" ).set_host_address( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
1059 : @endcode
1060 :
1061 : @par Postconditions
1062 : @code
1063 : this->has_authority() == true
1064 : @endcode
1065 :
1066 : @par Complexity
1067 : Linear in `s.size()`.
1068 :
1069 : @par Exception Safety
1070 : Strong guarantee.
1071 : Calls to allocate may throw.
1072 :
1073 : @par BNF
1074 : @code
1075 : IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
1076 :
1077 : dec-octet = DIGIT ; 0-9
1078 : / %x31-39 DIGIT ; 10-99
1079 : / "1" 2DIGIT ; 100-199
1080 : / "2" %x30-34 DIGIT ; 200-249
1081 : / "25" %x30-35 ; 250-255
1082 :
1083 : IPv6address = 6( h16 ":" ) ls32
1084 : / "::" 5( h16 ":" ) ls32
1085 : / [ h16 ] "::" 4( h16 ":" ) ls32
1086 : / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
1087 : / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
1088 : / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
1089 : / [ *4( h16 ":" ) h16 ] "::" ls32
1090 : / [ *5( h16 ":" ) h16 ] "::" h16
1091 : / [ *6( h16 ":" ) h16 ] "::"
1092 :
1093 : ls32 = ( h16 ":" h16 ) / IPv4address
1094 : ; least-significant 32 bits of address
1095 :
1096 : h16 = 1*4HEXDIG
1097 : ; 16 bits of address represented in hexadecimal
1098 :
1099 : IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1100 :
1101 : reg-name = *( unreserved / pct-encoded / "-" / ".")
1102 : @endcode
1103 :
1104 : @param s The string to set.
1105 : @return `*this`
1106 :
1107 : @par Specification
1108 : @li <a href="https://en.wikipedia.org/wiki/IPv4"
1109 : >IPv4 (Wikipedia)</a>
1110 : @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
1111 : >IP Version 6 Addressing Architecture (rfc4291)</a>
1112 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1113 : 3.2.2. Host (rfc3986)</a>
1114 :
1115 : @see
1116 : @ref set_encoded_host,
1117 : @ref set_encoded_host_address,
1118 : @ref set_encoded_host_name,
1119 : @ref set_host,
1120 : @ref set_host_address,
1121 : @ref set_host_ipv4,
1122 : @ref set_host_ipv6,
1123 : @ref set_host_ipvfuture,
1124 : @ref set_host_name.
1125 : */
1126 : url_base&
1127 : set_host_address(core::string_view s);
1128 :
1129 : /** Set the host to an address
1130 :
1131 : Depending on the contents of the passed
1132 : string, this function sets the host:
1133 :
1134 : @li If the string is a valid IPv4 address,
1135 : then the host is set to the address.
1136 : The host type is @ref host_type::ipv4.
1137 :
1138 : @li If the string is a valid IPv6 address,
1139 : then the host is set to that address.
1140 : The host type is @ref host_type::ipv6.
1141 :
1142 : @li If the string is a valid IPvFuture,
1143 : then the host is set to that address.
1144 : The host type is @ref host_type::ipvfuture.
1145 :
1146 : @li Otherwise, the host name is set to
1147 : the string. This string can contain percent
1148 : escapes, or can be empty.
1149 : Escapes in the string are preserved,
1150 : and reserved characters in the string
1151 : are percent-escaped in the result.
1152 : The host type is @ref host_type::name.
1153 :
1154 : In all cases, when this function returns,
1155 : the URL contains an authority.
1156 :
1157 : @par Example
1158 : @code
1159 : assert( url( "http://www.example.com" ).set_host( "127.0.0.1" ).buffer() == "http://127.0.0.1" );
1160 : @endcode
1161 :
1162 : @par Postconditions
1163 : @code
1164 : this->has_authority() == true
1165 : @endcode
1166 :
1167 : @par Complexity
1168 : Linear in `this->size() + s.size()`.
1169 :
1170 : @par Exception Safety
1171 : Strong guarantee.
1172 : Calls to allocate may throw.
1173 : Exceptions thrown on invalid input.
1174 :
1175 : @throw system_error
1176 : `s` contains an invalid percent-encoding.
1177 :
1178 : @par BNF
1179 : @code
1180 : IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
1181 :
1182 : dec-octet = DIGIT ; 0-9
1183 : / %x31-39 DIGIT ; 10-99
1184 : / "1" 2DIGIT ; 100-199
1185 : / "2" %x30-34 DIGIT ; 200-249
1186 : / "25" %x30-35 ; 250-255
1187 :
1188 : IPv6address = 6( h16 ":" ) ls32
1189 : / "::" 5( h16 ":" ) ls32
1190 : / [ h16 ] "::" 4( h16 ":" ) ls32
1191 : / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
1192 : / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
1193 : / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
1194 : / [ *4( h16 ":" ) h16 ] "::" ls32
1195 : / [ *5( h16 ":" ) h16 ] "::" h16
1196 : / [ *6( h16 ":" ) h16 ] "::"
1197 :
1198 : ls32 = ( h16 ":" h16 ) / IPv4address
1199 : ; least-significant 32 bits of address
1200 :
1201 : h16 = 1*4HEXDIG
1202 : ; 16 bits of address represented in hexadecimal
1203 :
1204 : IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1205 :
1206 : reg-name = *( unreserved / pct-encoded / "-" / ".")
1207 : @endcode
1208 :
1209 : @param s The string to set.
1210 : @return `*this`
1211 :
1212 : @par Specification
1213 : @li <a href="https://en.wikipedia.org/wiki/IPv4"
1214 : >IPv4 (Wikipedia)</a>
1215 : @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
1216 : >IP Version 6 Addressing Architecture (rfc4291)</a>
1217 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1218 : 3.2.2. Host (rfc3986)</a>
1219 :
1220 : @see
1221 : @ref set_encoded_host,
1222 : @ref set_encoded_host_name,
1223 : @ref set_host,
1224 : @ref set_host_address,
1225 : @ref set_host_ipv4,
1226 : @ref set_host_ipv6,
1227 : @ref set_host_ipvfuture,
1228 : @ref set_host_name.
1229 : */
1230 : url_base&
1231 : set_encoded_host_address(
1232 : pct_string_view s);
1233 :
1234 : /** Set the host to an address
1235 :
1236 : The host is set to the specified IPv4
1237 : address.
1238 : The host type is @ref host_type::ipv4.
1239 :
1240 : @par Example
1241 : @code
1242 : assert( url("http://www.example.com").set_host_ipv4( ipv4_address( "127.0.0.1" ) ).buffer() == "http://127.0.0.1" );
1243 : @endcode
1244 :
1245 : @par Complexity
1246 : Linear in `this->size()`.
1247 :
1248 : @par Postconditions
1249 : @code
1250 : this->has_authority() == true && this->host_ipv4_address() == addr && this->host_type() == host_type::ipv4
1251 : @endcode
1252 :
1253 : @par Exception Safety
1254 : Strong guarantee.
1255 : Calls to allocate may throw.
1256 :
1257 : @param addr The address to set.
1258 : @return `*this`
1259 :
1260 : @par BNF
1261 : @code
1262 : IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
1263 :
1264 : dec-octet = DIGIT ; 0-9
1265 : / %x31-39 DIGIT ; 10-99
1266 : / "1" 2DIGIT ; 100-199
1267 : / "2" %x30-34 DIGIT ; 200-249
1268 : / "25" %x30-35 ; 250-255
1269 : @endcode
1270 :
1271 : @par Specification
1272 : @li <a href="https://en.wikipedia.org/wiki/IPv4"
1273 : >IPv4 (Wikipedia)</a>
1274 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1275 : 3.2.2. Host (rfc3986)</a>
1276 :
1277 : @see
1278 : @ref set_encoded_host,
1279 : @ref set_encoded_host_address,
1280 : @ref set_encoded_host_name,
1281 : @ref set_host,
1282 : @ref set_host_address,
1283 : @ref set_host_ipv6,
1284 : @ref set_host_ipvfuture,
1285 : @ref set_host_name.
1286 : */
1287 : url_base&
1288 : set_host_ipv4(
1289 : ipv4_address const& addr);
1290 :
1291 : /** Set the host to an address
1292 :
1293 : The host is set to the specified IPv6
1294 : address.
1295 : The host type is @ref host_type::ipv6.
1296 :
1297 : @par Example
1298 : @code
1299 : assert( url().set_host_ipv6( ipv6_address( "1::6:c0a8:1" ) ).authority().buffer() == "[1::6:c0a8:1]" );
1300 : @endcode
1301 :
1302 : @par Postconditions
1303 : @code
1304 : this->has_authority() == true && this->host_ipv6_address() == addr && this->host_type() == host_type::ipv6
1305 : @endcode
1306 :
1307 : @par Complexity
1308 : Linear in `this->size()`.
1309 :
1310 : @par Exception Safety
1311 : Strong guarantee.
1312 : Calls to allocate may throw.
1313 :
1314 : @param addr The address to set.
1315 :
1316 : @return `*this`
1317 :
1318 : @par BNF
1319 : @code
1320 : IPv6address = 6( h16 ":" ) ls32
1321 : / "::" 5( h16 ":" ) ls32
1322 : / [ h16 ] "::" 4( h16 ":" ) ls32
1323 : / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
1324 : / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
1325 : / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
1326 : / [ *4( h16 ":" ) h16 ] "::" ls32
1327 : / [ *5( h16 ":" ) h16 ] "::" h16
1328 : / [ *6( h16 ":" ) h16 ] "::"
1329 :
1330 : ls32 = ( h16 ":" h16 ) / IPv4address
1331 : ; least-significant 32 bits of address
1332 :
1333 : h16 = 1*4HEXDIG
1334 : ; 16 bits of address represented in hexadecimal
1335 : @endcode
1336 :
1337 : @par Specification
1338 : @li <a href="https://datatracker.ietf.org/doc/html/rfc4291"
1339 : >IP Version 6 Addressing Architecture (rfc4291)</a>
1340 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1341 : 3.2.2. Host (rfc3986)</a>
1342 :
1343 : @see
1344 : @ref set_encoded_host,
1345 : @ref set_encoded_host_address,
1346 : @ref set_encoded_host_name,
1347 : @ref set_host,
1348 : @ref set_host_address,
1349 : @ref set_host_ipv4,
1350 : @ref set_host_ipvfuture,
1351 : @ref set_host_name.
1352 : */
1353 : url_base&
1354 : set_host_ipv6(
1355 : ipv6_address const& addr);
1356 :
1357 : /** Set the zone ID for an IPv6 address.
1358 :
1359 : This function sets the zone ID for the host if the host is an IPv6 address.
1360 : Reserved characters in the string are percent-escaped in the result.
1361 :
1362 : @par Example
1363 : @code
1364 : assert( u.set_host_ipv6( ipv6_address( "fe80::1" ) ).set_zone_id( "eth0" ).buffer() == "https://[fe80::1%25eth0]" );
1365 : @endcode
1366 :
1367 : @par Complexity
1368 : Linear in `this->size()`.
1369 :
1370 : @par Exception Safety
1371 : Strong guarantee. Calls to allocate may throw.
1372 :
1373 : @param s The zone ID to set.
1374 : @return `*this`
1375 :
1376 : @par Specification
1377 : @li <a href="https://datatracker.ietf.org/doc/html/rfc6874">RFC 6874</a>
1378 :
1379 : */
1380 : url_base&
1381 : set_zone_id(core::string_view s);
1382 :
1383 : /** Set the zone ID for an IPv6 address (percent-encoded).
1384 :
1385 : This function sets the zone ID for the host if the host is an IPv6 address.
1386 : Escapes in the string are preserved, and reserved characters in the string
1387 : are percent-escaped in the result.
1388 :
1389 : @par Example
1390 : @code
1391 : assert( u.set_host_ipv6( ipv6_address( "fe80::1" ) ).set_encoded_zone_id( "eth0" ).buffer() == "https://[fe80::1%25eth0]" );
1392 : @endcode
1393 :
1394 : @par Complexity
1395 : Linear in `this->size()`.
1396 :
1397 : @par Exception Safety
1398 : Strong guarantee. Calls to allocate may throw.
1399 : Exceptions thrown on invalid input.
1400 :
1401 : @throw system_error
1402 : `s` contains an invalid percent-encoding.
1403 :
1404 : @param s The zone ID to set.
1405 : @return `*this`
1406 :
1407 : @par Specification
1408 : @li <a href="https://datatracker.ietf.org/doc/html/rfc6874">RFC 6874</a>
1409 :
1410 : */
1411 : url_base&
1412 : set_encoded_zone_id(pct_string_view s);
1413 :
1414 : /** Set the host to an address
1415 :
1416 : The host is set to the specified IPvFuture
1417 : string.
1418 : The host type is @ref host_type::ipvfuture.
1419 :
1420 : @par Example
1421 : @code
1422 : assert( url().set_host_ipvfuture( "v42.bis" ).buffer() == "//[v42.bis]" );
1423 : @endcode
1424 :
1425 : @par Complexity
1426 : Linear in `this->size() + s.size()`.
1427 :
1428 : @par Postconditions
1429 : @code
1430 : this->has_authority() == true && this->host_ipvfuture) == s && this->host_type() == host_type::ipvfuture
1431 : @endcode
1432 :
1433 : @par Exception Safety
1434 : Strong guarantee.
1435 : Calls to allocate may throw.
1436 : Exceptions thrown on invalid input.
1437 :
1438 : @throw system_error
1439 : `s` contains an invalid percent-encoding.
1440 :
1441 : @param s The string to set.
1442 :
1443 : @return `*this`
1444 :
1445 : @par BNF
1446 : @code
1447 : IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
1448 : @endcode
1449 :
1450 : @par Specification
1451 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1452 : 3.2.2. Host (rfc3986)</a>
1453 :
1454 : @see
1455 : @ref set_encoded_host,
1456 : @ref set_encoded_host_address,
1457 : @ref set_encoded_host_name,
1458 : @ref set_host,
1459 : @ref set_host_address,
1460 : @ref set_host_ipv4,
1461 : @ref set_host_ipv6,
1462 : @ref set_host_name.
1463 : */
1464 : url_base&
1465 : set_host_ipvfuture(
1466 : core::string_view s);
1467 :
1468 : /** Set the host to a name
1469 :
1470 : The host is set to the specified string,
1471 : which may be empty.
1472 : Reserved characters in the string are
1473 : percent-escaped in the result.
1474 : The host type is @ref host_type::name.
1475 :
1476 : @par Example
1477 : @code
1478 : assert( url( "http://www.example.com/index.htm").set_host_name( "localhost" ).host_address() == "localhost" );
1479 : @endcode
1480 :
1481 : @par Postconditions
1482 : @code
1483 : this->has_authority() == true && this->host_ipv6_address() == addr && this->host_type() == host_type::name
1484 : @endcode
1485 :
1486 : @par Exception Safety
1487 : Strong guarantee.
1488 : Calls to allocate may throw.
1489 :
1490 : @param s The string to set.
1491 : @return `*this`
1492 :
1493 : @par BNF
1494 : @code
1495 : reg-name = *( unreserved / pct-encoded / "-" / ".")
1496 : @endcode
1497 :
1498 : @par Specification
1499 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1500 : 3.2.2. Host (rfc3986)</a>
1501 :
1502 : @see
1503 : @ref set_encoded_host,
1504 : @ref set_encoded_host_address,
1505 : @ref set_encoded_host_name,
1506 : @ref set_host,
1507 : @ref set_host_address,
1508 : @ref set_host_ipv4,
1509 : @ref set_host_ipv6,
1510 : @ref set_host_ipvfuture.
1511 : */
1512 : url_base&
1513 : set_host_name(
1514 : core::string_view s);
1515 :
1516 : /** Set the host to a name
1517 :
1518 : The host is set to the specified string,
1519 : which may contain percent-escapes and
1520 : can be empty.
1521 : Escapes in the string are preserved,
1522 : and reserved characters in the string
1523 : are percent-escaped in the result.
1524 : The host type is @ref host_type::name.
1525 :
1526 : @par Example
1527 : @code
1528 : assert( url( "http://www.example.com/index.htm").set_encoded_host_name( "localhost" ).host_address() == "localhost" );
1529 : @endcode
1530 :
1531 : @par Postconditions
1532 : @code
1533 : this->has_authority() == true && this->host_ipv6_address() == addr && this->host_type() == host_type::name
1534 : @endcode
1535 :
1536 : @par Exception Safety
1537 : Strong guarantee.
1538 : Calls to allocate may throw.
1539 : Exceptions thrown on invalid input.
1540 :
1541 : @throw system_error
1542 : `s` contains an invalid percent-encoding.
1543 :
1544 : @param s The string to set.
1545 : @return `*this`
1546 :
1547 : @par BNF
1548 : @code
1549 : reg-name = *( unreserved / pct-encoded / "-" / ".")
1550 : @endcode
1551 :
1552 : @par Specification
1553 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2">
1554 : 3.2.2. Host (rfc3986)</a>
1555 :
1556 : @see
1557 : @ref set_encoded_host,
1558 : @ref set_encoded_host_address,
1559 : @ref set_host,
1560 : @ref set_host_address,
1561 : @ref set_host_ipv4,
1562 : @ref set_host_ipv6,
1563 : @ref set_host_ipvfuture,
1564 : @ref set_host_name.
1565 : */
1566 : url_base&
1567 : set_encoded_host_name(
1568 : pct_string_view s);
1569 :
1570 : //--------------------------------------------
1571 :
1572 : /** Set the port
1573 :
1574 : The port is set to the specified integer.
1575 :
1576 : @par Example
1577 : @code
1578 : assert( url( "http://www.example.com" ).set_port_number( 8080 ).authority().buffer() == "www.example.com:8080" );
1579 : @endcode
1580 :
1581 : @par Postconditions
1582 : @code
1583 : this->has_authority() == true && this->has_port() == true && this->port_number() == n
1584 : @endcode
1585 :
1586 : @par Complexity
1587 : Linear in `this->size()`.
1588 :
1589 : @par Exception Safety
1590 : Strong guarantee.
1591 : Calls to allocate may throw.
1592 :
1593 : @param n The port number to set.
1594 :
1595 : @return `*this`
1596 :
1597 : @par BNF
1598 : @code
1599 : authority = [ userinfo "@" ] host [ ":" port ]
1600 :
1601 : port = *DIGIT
1602 : @endcode
1603 :
1604 : @par Specification
1605 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3">
1606 : 3.2.3. Port (rfc3986)</a>
1607 :
1608 : @see
1609 : @ref remove_port,
1610 : @ref set_port.
1611 : */
1612 : url_base&
1613 : set_port_number(std::uint16_t n);
1614 :
1615 : /** Set the port
1616 :
1617 : This port is set to the string, which
1618 : must contain only digits or be empty.
1619 : An empty port string is distinct from
1620 : having no port.
1621 :
1622 : @par Example
1623 : @code
1624 : assert( url( "http://www.example.com" ).set_port( "8080" ).authority().buffer() == "www.example.com:8080" );
1625 : @endcode
1626 :
1627 : @par Postconditions
1628 : @code
1629 : this->has_port() == true && this->port_number() == n && this->port() == std::to_string(n)
1630 : @endcode
1631 :
1632 : @par Exception Safety
1633 : Strong guarantee.
1634 : Calls to allocate may throw.
1635 : Exceptions thrown on invalid input.
1636 :
1637 : @throw system_error
1638 : `s` does not contain a valid port.
1639 :
1640 : @param s The port string to set.
1641 : @return `*this`
1642 :
1643 : @par BNF
1644 : @code
1645 : port = *DIGIT
1646 : @endcode
1647 :
1648 : @par Specification
1649 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3">
1650 : 3.2.3. Port (rfc3986)</a>
1651 :
1652 : @see
1653 : @ref remove_port,
1654 : @ref set_port.
1655 : */
1656 : url_base&
1657 : set_port(core::string_view s);
1658 :
1659 : /** Remove the port
1660 :
1661 : If a port exists, it is removed. The rest
1662 : of the authority is unchanged.
1663 :
1664 : @return `*this`
1665 :
1666 : @par Example
1667 : @code
1668 : assert( url( "http://www.example.com:80" ).remove_port().authority().buffer() == "www.example.com" );
1669 : @endcode
1670 :
1671 : @par Postconditions
1672 : @code
1673 : this->has_port() == false && this->port_number() == 0 && this->port() == ""
1674 : @endcode
1675 :
1676 : @par Complexity
1677 : Linear in `this->size()`.
1678 :
1679 : @par Exception Safety
1680 : Throws nothing.
1681 :
1682 : @par BNF
1683 : @code
1684 : authority = [ userinfo "@" ] host [ ":" port ]
1685 :
1686 : port = *DIGIT
1687 : @endcode
1688 :
1689 : @par Specification
1690 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.3">
1691 : 3.2.3. Port (rfc3986)</a>
1692 :
1693 : @see
1694 : @ref set_port.
1695 : */
1696 : url_base&
1697 : remove_port() noexcept;
1698 :
1699 : //--------------------------------------------
1700 : //
1701 : // Path
1702 : //
1703 : //--------------------------------------------
1704 :
1705 : /** Set if the path is absolute
1706 :
1707 : This function adjusts the path to make
1708 : it absolute or not, depending on the
1709 : parameter.
1710 :
1711 : @note
1712 : If an authority is present, the path
1713 : is always absolute. In this case, the
1714 : function has no effect.
1715 :
1716 : @par Example
1717 : @code
1718 : url u( "path/to/file.txt" );
1719 : assert( u.set_path_absolute( true ) );
1720 : assert( u.buffer() == "/path/to/file.txt" );
1721 : @endcode
1722 :
1723 : @par Postconditions
1724 : @code
1725 : this->is_path_absolute() == true && this->encoded_path().front() == '/'
1726 : @endcode
1727 :
1728 : @param absolute If `true`, the path is made absolute.
1729 :
1730 : @return true on success.
1731 :
1732 : @par Complexity
1733 : Linear in `this->size()`.
1734 :
1735 : @par BNF
1736 : @code
1737 : path = path-abempty ; begins with "/" or is empty
1738 : / path-absolute ; begins with "/" but not "//"
1739 : / path-noscheme ; begins with a non-colon segment
1740 : / path-rootless ; begins with a segment
1741 : / path-empty ; zero characters
1742 :
1743 : path-abempty = *( "/" segment )
1744 : path-absolute = "/" [ segment-nz *( "/" segment ) ]
1745 : path-noscheme = segment-nz-nc *( "/" segment )
1746 : path-rootless = segment-nz *( "/" segment )
1747 : path-empty = 0<pchar>
1748 : @endcode
1749 :
1750 : @par Specification
1751 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
1752 : >3.3. Path (rfc3986)</a>
1753 :
1754 : @see
1755 : @ref encoded_segments,
1756 : @ref segments,
1757 : @ref set_encoded_path,
1758 : @ref set_path.
1759 : */
1760 : bool
1761 : set_path_absolute(bool absolute);
1762 :
1763 : /** Set the path.
1764 :
1765 : This function sets the path to the
1766 : string, which may be empty.
1767 : Reserved characters in the string are
1768 : percent-escaped in the result.
1769 :
1770 : @note
1771 : The library may adjust the final result
1772 : to ensure that no other parts of the URL
1773 : are semantically affected.
1774 :
1775 : @note
1776 : This function does not encode '/' chars, which
1777 : are unreserved for paths but reserved for
1778 : path segments. If a path segment should include
1779 : encoded '/'s to differentiate it from path separators,
1780 : the functions @ref set_encoded_path or @ref segments
1781 : should be used instead.
1782 :
1783 : @par Example
1784 : @code
1785 : url u( "http://www.example.com" );
1786 :
1787 : u.set_path( "path/to/file.txt" );
1788 :
1789 : assert( u.path() == "/path/to/file.txt" );
1790 : @endcode
1791 :
1792 : @par Complexity
1793 : Linear in `this->size() + s.size()`.
1794 :
1795 : @par Exception Safety
1796 : Strong guarantee.
1797 : Calls to allocate may throw.
1798 :
1799 : @param s The string to set.
1800 : @return `*this`
1801 :
1802 : @par BNF
1803 : @code
1804 : path = path-abempty ; begins with "/" or is empty
1805 : / path-absolute ; begins with "/" but not "//"
1806 : / path-noscheme ; begins with a non-colon segment
1807 : / path-rootless ; begins with a segment
1808 : / path-empty ; zero characters
1809 :
1810 : path-abempty = *( "/" segment )
1811 : path-absolute = "/" [ segment-nz *( "/" segment ) ]
1812 : path-noscheme = segment-nz-nc *( "/" segment )
1813 : path-rootless = segment-nz *( "/" segment )
1814 : path-empty = 0<pchar>
1815 : @endcode
1816 :
1817 : @par Specification
1818 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
1819 : >3.3. Path (rfc3986)</a>
1820 :
1821 : @see
1822 : @ref encoded_segments,
1823 : @ref segments,
1824 : @ref set_encoded_path,
1825 : @ref set_path_absolute.
1826 : */
1827 : url_base&
1828 : set_path(
1829 : core::string_view s);
1830 :
1831 : /** Set the path.
1832 :
1833 : This function sets the path to the
1834 : string, which may contain percent-escapes
1835 : and can be empty.
1836 : Escapes in the string are preserved,
1837 : and reserved characters in the string
1838 : are percent-escaped in the result.
1839 :
1840 : @note
1841 : The library may adjust the final result
1842 : to ensure that no other parts of the url
1843 : is semantically affected.
1844 :
1845 : @par Example
1846 : @code
1847 : url u( "http://www.example.com" );
1848 :
1849 : u.set_encoded_path( "path/to/file.txt" );
1850 :
1851 : assert( u.encoded_path() == "/path/to/file.txt" );
1852 : @endcode
1853 :
1854 : @par Complexity
1855 : Linear in `this->size() + s.size()`.
1856 :
1857 : @par Exception Safety
1858 : Strong guarantee.
1859 : Calls to allocate may throw.
1860 : Exceptions thrown on invalid input.
1861 :
1862 : @throw system_error
1863 : `s` contains an invalid percent-encoding.
1864 :
1865 : @param s The string to set.
1866 :
1867 : @return `*this`
1868 :
1869 : @par BNF
1870 : @code
1871 : path = path-abempty ; begins with "/" or is empty
1872 : / path-absolute ; begins with "/" but not "//"
1873 : / path-noscheme ; begins with a non-colon segment
1874 : / path-rootless ; begins with a segment
1875 : / path-empty ; zero characters
1876 :
1877 : path-abempty = *( "/" segment )
1878 : path-absolute = "/" [ segment-nz *( "/" segment ) ]
1879 : path-noscheme = segment-nz-nc *( "/" segment )
1880 : path-rootless = segment-nz *( "/" segment )
1881 : path-empty = 0<pchar>
1882 : @endcode
1883 :
1884 : @par Specification
1885 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
1886 : >3.3. Path (rfc3986)</a>
1887 :
1888 : @see
1889 : @ref encoded_segments,
1890 : @ref segments,
1891 : @ref set_path,
1892 : @ref set_path_absolute.
1893 : */
1894 : url_base&
1895 : set_encoded_path(
1896 : pct_string_view s);
1897 :
1898 : /** Return the path as a container of segments
1899 :
1900 : This function returns a bidirectional
1901 : view of segments over the path.
1902 : The returned view references the same
1903 : underlying character buffer; ownership
1904 : is not transferred.
1905 : Any percent-escapes in strings returned
1906 : when iterating the view are decoded first.
1907 : The container is modifiable; changes
1908 : to the container are reflected in the
1909 : underlying URL.
1910 :
1911 : @return `*this`
1912 :
1913 : @par Example
1914 : @code
1915 : url u( "http://example.com/path/to/file.txt" );
1916 :
1917 : segments sv = u.segments();
1918 : @endcode
1919 :
1920 : @par Complexity
1921 : Constant.
1922 :
1923 : @par Exception Safety
1924 : Throws nothing.
1925 :
1926 : @par BNF
1927 : @code
1928 : path = path-abempty ; begins with "/" or is empty
1929 : / path-absolute ; begins with "/" but not "//"
1930 : / path-noscheme ; begins with a non-colon segment
1931 : / path-rootless ; begins with a segment
1932 : / path-empty ; zero characters
1933 :
1934 : path-abempty = *( "/" segment )
1935 : path-absolute = "/" [ segment-nz *( "/" segment ) ]
1936 : path-noscheme = segment-nz-nc *( "/" segment )
1937 : path-rootless = segment-nz *( "/" segment )
1938 : path-empty = 0<pchar>
1939 : @endcode
1940 :
1941 : @par Specification
1942 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
1943 : >3.3. Path (rfc3986)</a>
1944 :
1945 : @see
1946 : @ref encoded_segments,
1947 : @ref set_encoded_path,
1948 : @ref set_path,
1949 : @ref set_path_absolute.
1950 : */
1951 : urls::segments_ref
1952 : segments() noexcept;
1953 :
1954 : /// @copydoc url_view_base::segments
1955 : segments_view
1956 1 : segments() const noexcept
1957 : {
1958 1 : return url_view_base::segments();
1959 : }
1960 :
1961 : /** Return the path as a container of segments
1962 :
1963 : This function returns a bidirectional
1964 : view of segments over the path.
1965 : The returned view references the same
1966 : underlying character buffer; ownership
1967 : is not transferred.
1968 : Strings returned when iterating the
1969 : range may contain percent escapes.
1970 : The container is modifiable; changes
1971 : to the container are reflected in the
1972 : underlying URL.
1973 :
1974 : @return `*this`
1975 :
1976 : @par Example
1977 : @code
1978 : url u( "http://example.com/path/to/file.txt" );
1979 :
1980 : segments_encoded_ref sv = u.encoded_segments();
1981 : @endcode
1982 :
1983 : @par Complexity
1984 : Constant.
1985 :
1986 : @par Exception Safety
1987 : Throws nothing.
1988 :
1989 : @par BNF
1990 : @code
1991 : path = path-abempty ; begins with "/" or is empty
1992 : / path-absolute ; begins with "/" but not "//"
1993 : / path-noscheme ; begins with a non-colon segment
1994 : / path-rootless ; begins with a segment
1995 : / path-empty ; zero characters
1996 :
1997 : path-abempty = *( "/" segment )
1998 : path-absolute = "/" [ segment-nz *( "/" segment ) ]
1999 : path-noscheme = segment-nz-nc *( "/" segment )
2000 : path-rootless = segment-nz *( "/" segment )
2001 : path-empty = 0<pchar>
2002 : @endcode
2003 :
2004 : @par Specification
2005 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.3"
2006 : >3.3. Path (rfc3986)</a>
2007 :
2008 : @see
2009 : @ref encoded_segments,
2010 : @ref set_encoded_path,
2011 : @ref set_path,
2012 : @ref set_path_absolute.
2013 : */
2014 : segments_encoded_ref
2015 : encoded_segments() noexcept;
2016 :
2017 : /// @copydoc url_view_base::encoded_segments
2018 : segments_encoded_view
2019 1 : encoded_segments() const noexcept
2020 : {
2021 1 : return url_view_base::encoded_segments();
2022 : }
2023 :
2024 : //--------------------------------------------
2025 : //
2026 : // Query
2027 : //
2028 : //--------------------------------------------
2029 :
2030 : /** Set the query
2031 :
2032 : This sets the query to the string, which
2033 : can be empty.
2034 : An empty query is distinct from having
2035 : no query.
2036 : Reserved characters in the string are
2037 : percent-escaped in the result.
2038 :
2039 : @par Example
2040 : @code
2041 : assert( url( "http://example.com" ).set_query( "id=42" ).query() == "id=42" );
2042 : @endcode
2043 :
2044 : @par Postconditions
2045 : @code
2046 : this->has_query() == true && this->query() == s
2047 : @endcode
2048 :
2049 : @par Exception Safety
2050 : Strong guarantee.
2051 : Calls to allocate may throw.
2052 :
2053 : @param s The string to set.
2054 : @return `*this`
2055 :
2056 : @par BNF
2057 : @code
2058 : query = *( pchar / "/" / "?" )
2059 :
2060 : query-param = key [ "=" value ]
2061 : query-params = [ query-param ] *( "&" query-param )
2062 : @endcode
2063 :
2064 : @par Specification
2065 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2066 : >3.4. Query (rfc3986)</a>
2067 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
2068 : >Query string (Wikipedia)</a>
2069 :
2070 : @see
2071 : @ref encoded_params,
2072 : @ref params,
2073 : @ref remove_query,
2074 : @ref set_encoded_query.
2075 : */
2076 : url_base&
2077 : set_query(
2078 : core::string_view s);
2079 :
2080 : /** Set the query
2081 :
2082 : This sets the query to the string, which
2083 : may contain percent-escapes and can be
2084 : empty.
2085 : An empty query is distinct from having
2086 : no query.
2087 : Escapes in the string are preserved,
2088 : and reserved characters in the string
2089 : are percent-escaped in the result.
2090 :
2091 : @par Example
2092 : @code
2093 : assert( url( "http://example.com" ).set_encoded_query( "id=42" ).encoded_query() == "id=42" );
2094 : @endcode
2095 :
2096 : @par Postconditions
2097 : @code
2098 : this->has_query() == true && this->query() == decode_view( s );
2099 : @endcode
2100 :
2101 : @par Exception Safety
2102 : Strong guarantee.
2103 : Calls to allocate may throw.
2104 : Exceptions thrown on invalid input.
2105 :
2106 : @param s The string to set.
2107 : @return `*this`
2108 :
2109 : @throws system_error
2110 : `s` contains an invalid percent-encoding.
2111 :
2112 : @par BNF
2113 : @code
2114 : query = *( pchar / "/" / "?" )
2115 :
2116 : query-param = key [ "=" value ]
2117 : query-params = [ query-param ] *( "&" query-param )
2118 : @endcode
2119 :
2120 : @par Specification
2121 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2122 : >3.4. Query (rfc3986)</a>
2123 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
2124 : >Query string (Wikipedia)</a>
2125 :
2126 : @see
2127 : @ref encoded_params,
2128 : @ref params,
2129 : @ref remove_query,
2130 : @ref set_query.
2131 : */
2132 : url_base&
2133 : set_encoded_query(
2134 : pct_string_view s);
2135 :
2136 : /** Return the query as a container of parameters
2137 :
2138 : This function returns a bidirectional
2139 : view of key/value pairs over the query.
2140 : The returned view references the same
2141 : underlying character buffer; ownership
2142 : is not transferred.
2143 : Any percent-escapes in strings returned
2144 : when iterating the view are decoded first.
2145 : The container is modifiable; changes
2146 : to the container are reflected in the
2147 : underlying URL.
2148 :
2149 : @return `*this`
2150 :
2151 : @par Example
2152 : @code
2153 : params_ref pv = url( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).params();
2154 : @endcode
2155 :
2156 : @par Complexity
2157 : Constant.
2158 :
2159 : @par Exception Safety
2160 : Throws nothing.
2161 :
2162 : @par BNF
2163 : @code
2164 : query = *( pchar / "/" / "?" )
2165 :
2166 : query-param = key [ "=" value ]
2167 : query-params = [ query-param ] *( "&" query-param )
2168 : @endcode
2169 :
2170 : @par Specification
2171 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2172 : >3.4. Query (rfc3986)</a>
2173 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
2174 : >Query string (Wikipedia)</a>
2175 :
2176 : @see
2177 : @ref encoded_params,
2178 : @ref remove_query,
2179 : @ref set_encoded_query,
2180 : @ref set_query.
2181 : */
2182 : params_ref
2183 : params() noexcept;
2184 :
2185 : /// @copydoc url_view_base::params
2186 : params_view
2187 1 : params() const noexcept
2188 : {
2189 1 : return url_view_base::params();
2190 : }
2191 :
2192 : /** Return the query as a container of parameters
2193 :
2194 : This function returns a bidirectional
2195 : view of key/value pairs over the query.
2196 : The returned view references the same
2197 : underlying character buffer; ownership
2198 : is not transferred.
2199 : Any percent-escapes in strings returned
2200 : when iterating the view are decoded first.
2201 : The container is modifiable; changes
2202 : to the container are reflected in the
2203 : underlying URL.
2204 :
2205 : @par Example
2206 : @code
2207 : encoding_opts opt;
2208 : opt.space_as_plus = true;
2209 : params_ref pv = url( "/sql?id=42&name=jane+doe&page+size=20" ).params(opt);
2210 : @endcode
2211 :
2212 : @par Complexity
2213 : Constant.
2214 :
2215 : @par Exception Safety
2216 : Throws nothing.
2217 :
2218 : @param opt The options for decoding. If
2219 : this parameter is omitted, the `space_as_plus`
2220 : is used.
2221 :
2222 : @return A range of references to the parameters.
2223 :
2224 : @par BNF
2225 : @code
2226 : query = *( pchar / "/" / "?" )
2227 :
2228 : query-param = key [ "=" value ]
2229 : query-params = [ query-param ] *( "&" query-param )
2230 : @endcode
2231 :
2232 : @par Specification
2233 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2234 : >3.4. Query (rfc3986)</a>
2235 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
2236 : >Query string (Wikipedia)</a>
2237 :
2238 : @see
2239 : @ref encoded_params,
2240 : @ref remove_query,
2241 : @ref set_encoded_query,
2242 : @ref set_query.
2243 : */
2244 : params_ref
2245 : params(encoding_opts opt) noexcept;
2246 :
2247 : /// @copydoc url_view_base::encoded_params
2248 : params_encoded_view
2249 1 : encoded_params() const noexcept
2250 : {
2251 1 : return url_view_base::encoded_params();
2252 : }
2253 :
2254 : /** Return the query as a container of parameters
2255 :
2256 : This function returns a bidirectional
2257 : view of key/value pairs over the query.
2258 : The returned view references the same
2259 : underlying character buffer; ownership
2260 : is not transferred.
2261 : Strings returned when iterating the
2262 : range may contain percent escapes.
2263 : The container is modifiable; changes
2264 : to the container are reflected in the
2265 : underlying URL.
2266 :
2267 : @return `*this`
2268 :
2269 : @par Example
2270 : @code
2271 : params_encoded_ref pv = url( "/sql?id=42&name=jane%2Ddoe&page+size=20" ).encoded_params();
2272 : @endcode
2273 :
2274 : @par Complexity
2275 : Constant.
2276 :
2277 : @par Exception Safety
2278 : Throws nothing.
2279 :
2280 : @par BNF
2281 : @code
2282 : query = *( pchar / "/" / "?" )
2283 :
2284 : query-param = key [ "=" value ]
2285 : query-params = [ query-param ] *( "&" query-param )
2286 : @endcode
2287 :
2288 : @par Specification
2289 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2290 : >3.4. Query (rfc3986)</a>
2291 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
2292 : >Query string (Wikipedia)</a>
2293 :
2294 : @see
2295 : @ref params,
2296 : @ref remove_query,
2297 : @ref set_encoded_query,
2298 : @ref set_query.
2299 : */
2300 : params_encoded_ref
2301 : encoded_params() noexcept;
2302 :
2303 : /** Set the query params
2304 :
2305 : This sets the query params to the list
2306 : of param_view, which can be empty.
2307 :
2308 : An empty list of params is distinct from
2309 : having no params.
2310 :
2311 : Reserved characters in the string are
2312 : percent-escaped in the result.
2313 :
2314 : @par Example
2315 : @code
2316 : assert( url( "http://example.com" ).set_params( {"id", "42"} ).query() == "id=42" );
2317 : @endcode
2318 :
2319 : @par Postconditions
2320 : @code
2321 : this->has_query() == true
2322 : @endcode
2323 :
2324 : @par Exception Safety
2325 : Strong guarantee.
2326 : Calls to allocate may throw.
2327 :
2328 : @par Complexity
2329 : Linear.
2330 :
2331 : @param ps The params to set.
2332 : @param opts The options for encoding.
2333 : @return `*this`
2334 :
2335 : @par BNF
2336 : @code
2337 : query = *( pchar / "/" / "?" )
2338 :
2339 : query-param = key [ "=" value ]
2340 : query-params = [ query-param ] *( "&" query-param )
2341 : @endcode
2342 :
2343 : @par Specification
2344 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4
2345 : >3.4. Query (rfc3986)</a>
2346 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
2347 : >Query string (Wikipedia)</a>
2348 :
2349 : @see
2350 : @ref encoded_params,
2351 : @ref remove_query,
2352 : @ref set_encoded_query,
2353 : @ref set_query.
2354 : */
2355 : url_base&
2356 : set_params(
2357 : std::initializer_list<param_view> ps,
2358 : encoding_opts opts = {}) noexcept;
2359 :
2360 : /** Set the query params
2361 :
2362 : This sets the query params to the elements
2363 : in the list, which may contain
2364 : percent-escapes and can be empty.
2365 :
2366 : An empty list of params is distinct from
2367 : having no query.
2368 :
2369 : Escapes in the string are preserved,
2370 : and reserved characters in the string
2371 : are percent-escaped in the result.
2372 :
2373 : @par Example
2374 : @code
2375 : assert( url( "http://example.com" ).set_encoded_params( {"id", "42"} ).encoded_query() == "id=42" );
2376 : @endcode
2377 :
2378 : @par Postconditions
2379 : @code
2380 : this->has_query() == true
2381 : @endcode
2382 :
2383 : @par Complexity
2384 : Linear.
2385 :
2386 : @par Exception Safety
2387 : Strong guarantee.
2388 : Calls to allocate may throw.
2389 : Exceptions thrown on invalid input.
2390 :
2391 : @param ps The params to set.
2392 :
2393 : @return `*this`
2394 :
2395 : @throws system_error
2396 : some element in `ps` contains an invalid percent-encoding.
2397 :
2398 : @par BNF
2399 : @code
2400 : query = *( pchar / "/" / "?" )
2401 :
2402 : query-param = key [ "=" value ]
2403 : query-params = [ query-param ] *( "&" query-param )
2404 : @endcode
2405 :
2406 : @par Specification
2407 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2408 : >3.4. Query (rfc3986)</a>
2409 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
2410 : >Query string (Wikipedia)</a>
2411 :
2412 : @see
2413 : @ref set_params,
2414 : @ref params,
2415 : @ref remove_query,
2416 : @ref set_encoded_query,
2417 : @ref set_query.
2418 : */
2419 : url_base&
2420 : set_encoded_params( std::initializer_list< param_pct_view > ps ) noexcept;
2421 :
2422 : /** Remove the query
2423 :
2424 : If a query is present, it is removed.
2425 : An empty query is distinct from having
2426 : no query.
2427 :
2428 : @return `*this`
2429 :
2430 : @par Example
2431 : @code
2432 : assert( url( "http://www.example.com?id=42" ).remove_query().buffer() == "http://www.example.com" );
2433 : @endcode
2434 :
2435 : @par Postconditions
2436 : @code
2437 : this->has_query() == false && this->params().empty()
2438 : @endcode
2439 :
2440 : @par Exception Safety
2441 : Throws nothing.
2442 :
2443 : @par BNF
2444 : @code
2445 : query = *( pchar / "/" / "?" )
2446 :
2447 : query-param = key [ "=" value ]
2448 : query-params = [ query-param ] *( "&" query-param )
2449 : @endcode
2450 :
2451 : @par Specification
2452 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.4"
2453 : >3.4. Query (rfc3986)</a>
2454 : @li <a href="https://en.wikipedia.org/wiki/Query_string"
2455 : >Query string (Wikipedia)</a>
2456 :
2457 : @see
2458 : @ref encoded_params,
2459 : @ref params,
2460 : @ref set_encoded_query,
2461 : @ref set_query.
2462 : */
2463 : url_base&
2464 : remove_query() noexcept;
2465 :
2466 : //--------------------------------------------
2467 : //
2468 : // Fragment
2469 : //
2470 : //--------------------------------------------
2471 :
2472 : /** Remove the fragment
2473 :
2474 : This function removes the fragment.
2475 : An empty fragment is distinct from
2476 : having no fragment.
2477 :
2478 : @return `*this`
2479 :
2480 : @par Example
2481 : @code
2482 : assert( url( "?first=john&last=doe#anchor" ).remove_fragment().buffer() == "?first=john&last=doe" );
2483 : @endcode
2484 :
2485 : @par Postconditions
2486 : @code
2487 : this->has_fragment() == false && this->encoded_fragment() == ""
2488 : @endcode
2489 :
2490 : @par Complexity
2491 : Constant.
2492 :
2493 : @par Exception Safety
2494 : Throws nothing.
2495 :
2496 : @par BNF
2497 : @code
2498 : fragment = *( pchar / "/" / "?" )
2499 : @endcode
2500 :
2501 : @par Specification
2502 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.5"
2503 : >3.5. Fragment</a>
2504 :
2505 : @see
2506 : @ref remove_fragment,
2507 : @ref set_encoded_fragment,
2508 : @ref set_fragment.
2509 : */
2510 : url_base&
2511 : remove_fragment() noexcept;
2512 :
2513 : /** Set the fragment.
2514 :
2515 : This function sets the fragment to the
2516 : specified string, which may be empty.
2517 : An empty fragment is distinct from
2518 : having no fragment.
2519 : Reserved characters in the string are
2520 : percent-escaped in the result.
2521 :
2522 : @par Example
2523 : @code
2524 : assert( url("?first=john&last=doe" ).set_encoded_fragment( "john doe" ).encoded_fragment() == "john%20doe" );
2525 : @endcode
2526 :
2527 : @par Postconditions
2528 : @code
2529 : this->has_fragment() == true && this->fragment() == s
2530 : @endcode
2531 :
2532 : @par Complexity
2533 : Linear in `this->size() + s.size()`.
2534 :
2535 : @par Exception Safety
2536 : Strong guarantee.
2537 : Calls to allocate may throw.
2538 :
2539 : @param s The string to set.
2540 :
2541 : @return `*this`
2542 :
2543 : @par BNF
2544 : @code
2545 : fragment = *( pchar / "/" / "?" )
2546 : @endcode
2547 :
2548 : @par Specification
2549 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.5"
2550 : >3.5. Fragment</a>
2551 :
2552 : @see
2553 : @ref remove_fragment,
2554 : @ref set_encoded_fragment.
2555 : */
2556 : url_base&
2557 : set_fragment(
2558 : core::string_view s);
2559 :
2560 : /** Set the fragment.
2561 :
2562 : This function sets the fragment to the
2563 : specified string, which may contain
2564 : percent-escapes and which may be empty.
2565 : An empty fragment is distinct from
2566 : having no fragment.
2567 : Escapes in the string are preserved,
2568 : and reserved characters in the string
2569 : are percent-escaped in the result.
2570 :
2571 : @return `*this`
2572 :
2573 : @par Example
2574 : @code
2575 : assert( url("?first=john&last=doe" ).set_encoded_fragment( "john%2Ddoe" ).fragment() == "john-doe" );
2576 : @endcode
2577 :
2578 : @par Postconditions
2579 : @code
2580 : this->has_fragment() == true && this->fragment() == decode_view( s )
2581 : @endcode
2582 :
2583 : @par Complexity
2584 : Linear in `this->size() + s.size()`.
2585 :
2586 : @par Exception Safety
2587 : Strong guarantee.
2588 : Calls to allocate may throw.
2589 : Exceptions thrown on invalid input.
2590 :
2591 : @throw system_error
2592 : `s` contains an invalid percent-encoding.
2593 :
2594 : @param s The string to set.
2595 :
2596 : @return `*this`
2597 :
2598 : @par BNF
2599 : @code
2600 : fragment = *( pchar / "/" / "?" )
2601 : @endcode
2602 :
2603 : @par Specification
2604 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-3.5"
2605 : >3.5. Fragment</a>
2606 :
2607 : @see
2608 : @ref remove_fragment,
2609 : @ref set_fragment.
2610 : */
2611 : url_base&
2612 : set_encoded_fragment(
2613 : pct_string_view s);
2614 :
2615 : //--------------------------------------------
2616 : //
2617 : // Compound Fields
2618 : //
2619 : //--------------------------------------------
2620 :
2621 : /** Remove the origin component
2622 :
2623 : This function removes the origin, which
2624 : consists of the scheme and authority.
2625 :
2626 : @return `*this`
2627 :
2628 : @par Example
2629 : @code
2630 : assert( url( "http://www.example.com/index.htm" ).remove_origin().buffer() == "/index.htm" );
2631 : @endcode
2632 :
2633 : @par Postconditions
2634 : @code
2635 : this->scheme_id() == scheme::none && this->has_authority() == false
2636 : @endcode
2637 :
2638 : @par Complexity
2639 : Linear in `this->size()`.
2640 :
2641 : @par Exception Safety
2642 : Throws nothing.
2643 : */
2644 : url_base&
2645 : remove_origin();
2646 :
2647 : //--------------------------------------------
2648 : //
2649 : // Normalization
2650 : //
2651 : //--------------------------------------------
2652 :
2653 : /** Normalize the URL components
2654 :
2655 : Applies Syntax-based normalization to
2656 : all components of the URL.
2657 :
2658 : The scheme is normalized to lowercase.
2659 :
2660 : @code
2661 : assert( url( "HTTP://www.example.com" ).normalize().buffer() == "http://www.example.com" );
2662 : @endcode
2663 :
2664 : The host is normalized to lowercase.
2665 : Percent-encoding triplets are normalized
2666 : to uppercase letters. Percent-encoded
2667 : octets that correspond to unreserved
2668 : characters are decoded.
2669 :
2670 : @code
2671 : assert( url( "http://www.Example.com" ).normalize().buffer() == "http://www.example.com" );
2672 : assert( url( "http://www.%65xample.com" ).normalize().buffer() == "http://www.example.com" );
2673 : @endcode
2674 :
2675 : Percent-encoding triplets in the path
2676 : are normalized to uppercase letters.
2677 : Percent-encoded octets that correspond
2678 : to unreserved characters are decoded.
2679 : Redundant path-segments "." and ".."
2680 : are removed.
2681 :
2682 : @code
2683 : assert( url( "http://www.example.com/a/b/../c" ).normalize().buffer() == "http://www.example.com/a/c" );
2684 : assert( url( "http://www.example.com/a/./b" ).normalize().buffer() == "http://www.example.com/a/b" );
2685 : assert( url( "http://www.example.com/%63ss" ).normalize().buffer() == "http://www.example.com/css" );
2686 : @endcode
2687 :
2688 : Percent-encoding triplets in the query
2689 : are normalized to uppercase letters.
2690 : Percent-encoded octets that correspond
2691 : to unreserved characters are decoded.
2692 :
2693 : @code
2694 : assert( url( "http://www.example.com?a=%62" ).normalize().buffer() == "http://www.example.com?a=b" );
2695 : @endcode
2696 :
2697 : Percent-encoding triplets in the fragment
2698 : are normalized to uppercase letters.
2699 : Percent-encoded octets that correspond
2700 : to unreserved characters are decoded.
2701 :
2702 : @code
2703 : assert( url( "http://www.example.com#%61bc" ).normalize().buffer() == "http://www.example.com#abc" );
2704 : @endcode
2705 :
2706 : Applying normalization to a URL with all
2707 : components percent-encoded:
2708 :
2709 : @code
2710 : assert( url( "HTTP://www.Example.com/%70ath?%71uery#%66rag" ).normalize().buffer() == "http://www.example.com/path?query#frag" );
2711 : @endcode
2712 :
2713 : @return `*this`
2714 :
2715 : @par Exception Safety
2716 : Strong guarantee.
2717 : Calls to allocate may throw.
2718 :
2719 : @par Specification
2720 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2721 : >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2722 :
2723 : @see
2724 : @ref normalize_scheme,
2725 : @ref normalize_authority,
2726 : @ref normalize_path,
2727 : @ref normalize_query,
2728 : @ref normalize_fragment
2729 :
2730 : */
2731 : url_base&
2732 : normalize();
2733 :
2734 : /** Normalize the URL scheme
2735 :
2736 : Applies Syntax-based normalization to the
2737 : URL scheme.
2738 :
2739 : The scheme is normalized to lowercase.
2740 :
2741 : @code
2742 : assert( url( "HTTP://www.example.com" ).normalize_scheme().buffer() == "http://www.example.com" );
2743 : @endcode
2744 :
2745 : @return `*this`
2746 :
2747 : @par Exception Safety
2748 : Strong guarantee.
2749 : Calls to allocate may throw.
2750 :
2751 : @par Specification
2752 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2753 : >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2754 :
2755 : */
2756 : url_base&
2757 : normalize_scheme();
2758 :
2759 : /** Normalize the URL authority
2760 :
2761 : Applies Syntax-based normalization to the
2762 : URL authority.
2763 :
2764 : The host is normalized to lowercase.
2765 : Percent-encoding triplets are normalized
2766 : to uppercase letters. Percent-encoded
2767 : octets that correspond to unreserved
2768 : characters are decoded.
2769 :
2770 : @code
2771 : assert( url( "http://www.Example.com" ).normalize_authority().buffer() == "http://www.example.com" );
2772 : assert( url( "http://www.%65xample.com" ).normalize_authority().buffer() == "http://www.example.com" );
2773 : @endcode
2774 :
2775 : @return `*this`
2776 :
2777 : @par Exception Safety
2778 : Strong guarantee.
2779 : Calls to allocate may throw.
2780 :
2781 : @par Specification
2782 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2783 : >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2784 :
2785 : */
2786 : url_base&
2787 : normalize_authority();
2788 :
2789 : /** Normalize the URL path
2790 :
2791 : Applies Syntax-based normalization to the
2792 : URL path.
2793 :
2794 : Percent-encoding triplets are normalized
2795 : to uppercase letters. Percent-encoded
2796 : octets that correspond to unreserved
2797 : characters are decoded. Redundant
2798 : path-segments "." and ".." are removed.
2799 :
2800 : @code
2801 : assert( url( "http://www.example.com/a/b/../c" ).normalize_path().buffer() == "http://www.example.com/a/c" );
2802 : assert( url( "http://www.example.com/a/./b" ).normalize_path().buffer() == "http://www.example.com/a/b" );
2803 : assert( url( "http://www.example.com/%63ss" ).normalize_path().buffer() == "http://www.example.com/css" );
2804 : @endcode
2805 :
2806 : @return `*this`
2807 :
2808 : @par Exception Safety
2809 : Strong guarantee.
2810 : Calls to allocate may throw.
2811 :
2812 : @par Specification
2813 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2814 : >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2815 :
2816 : */
2817 : url_base&
2818 : normalize_path();
2819 :
2820 : /** Normalize the URL query
2821 :
2822 : Applies Syntax-based normalization to the
2823 : URL query.
2824 :
2825 : Percent-encoding triplets are normalized
2826 : to uppercase letters. Percent-encoded
2827 : octets that correspond to unreserved
2828 : characters are decoded.
2829 :
2830 : @code
2831 : assert( url( "http://www.example.com?a=%62" ).normalize_query().buffer() == "http://www.example.com?a=b" );
2832 : @endcode
2833 :
2834 : @return `*this`
2835 :
2836 : @par Exception Safety
2837 : Strong guarantee.
2838 : Calls to allocate may throw.
2839 :
2840 : @par Specification
2841 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2842 : >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2843 :
2844 : */
2845 : url_base&
2846 : normalize_query();
2847 :
2848 : /** Normalize the URL fragment
2849 :
2850 : Applies Syntax-based normalization to the
2851 : URL fragment.
2852 :
2853 : Percent-encoding triplets are normalized
2854 : to uppercase letters. Percent-encoded
2855 : octets that correspond to unreserved
2856 : characters are decoded.
2857 :
2858 : @code
2859 : assert( url( "http://www.example.com#%61bc" ).normalize_fragment().buffer() == "http://www.example.com#abc" );
2860 : @endcode
2861 :
2862 : @return `*this`
2863 :
2864 : @par Exception Safety
2865 : Strong guarantee.
2866 : Calls to allocate may throw.
2867 :
2868 : @par Specification
2869 : @li <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-6.2.2"
2870 : >6.2.2 Syntax-Based Normalization (rfc3986)</a>
2871 :
2872 : */
2873 : url_base&
2874 : normalize_fragment();
2875 :
2876 : //
2877 : // (end of fluent API)
2878 : //
2879 : //--------------------------------------------
2880 :
2881 : //--------------------------------------------
2882 : //
2883 : // Resolution
2884 : //
2885 : //--------------------------------------------
2886 :
2887 : /** Resolve a URL reference against this base URL
2888 :
2889 : This function attempts to resolve a URL
2890 : reference `ref` against this base URL
2891 : in a manner similar to that of a web browser
2892 : resolving an anchor tag.
2893 :
2894 : This URL must satisfy the <em>URI</em>
2895 : grammar. In other words, it must contain
2896 : a scheme.
2897 :
2898 : Relative references are only usable when
2899 : in the context of a base absolute URI.
2900 : This process of resolving a relative
2901 : <em>reference</em> within the context of
2902 : a <em>base</em> URI is defined in detail
2903 : in rfc3986 (see below).
2904 :
2905 : The resolution process works as if the
2906 : relative reference is appended to the base
2907 : URI and the result is normalized.
2908 :
2909 : Given the input base URL, this function
2910 : resolves the relative reference
2911 : as if performing the following steps:
2912 :
2913 : @li Ensure the base URI has at least a scheme
2914 : @li Normalizing the reference path
2915 : @li Merge base and reference paths
2916 : @li Normalize the merged path
2917 :
2918 : This function places the result of the
2919 : resolution into this URL in place.
2920 :
2921 : If an error occurs, the contents of
2922 : this URL are unspecified and a `boost::system::result`
2923 : with an `system::error_code` is returned.
2924 :
2925 : @note Abnormal hrefs where the number of ".."
2926 : segments exceeds the number of segments in
2927 : the base path are handled by including the
2928 : unmatched ".." segments in the result, as described
2929 : in <a href="https://www.rfc-editor.org/errata/eid4547"
2930 : >Errata 4547</a>.
2931 :
2932 : @par Example
2933 : @code
2934 : url base1( "/one/two/three" );
2935 : base1.resolve("four");
2936 : assert( base1.buffer() == "/one/two/four" );
2937 :
2938 : url base2( "http://example.com/" )
2939 : base2.resolve("/one");
2940 : assert( base2.buffer() == "http://example.com/one" );
2941 :
2942 : url base3( "http://example.com/one" );
2943 : base3.resolve("/two");
2944 : assert( base3.buffer() == "http://example.com/two" );
2945 :
2946 : url base4( "http://a/b/c/d;p?q" );
2947 : base4.resolve("g#s");
2948 : assert( base4.buffer() == "http://a/b/c/g#s" );
2949 : @endcode
2950 :
2951 : @par BNF
2952 : @code
2953 : absolute-URI = scheme ":" hier-part [ "?" query ]
2954 : @endcode
2955 :
2956 : @par Exception Safety
2957 : Basic guarantee.
2958 : Calls to allocate may throw.
2959 :
2960 : @return An empty `boost::system::result` upon success,
2961 : otherwise an error code if `!base.has_scheme()`.
2962 :
2963 : @param ref The URL reference to resolve.
2964 :
2965 : @par Specification
2966 : <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-5"
2967 : >5. Reference Resolution (rfc3986)</a>
2968 :
2969 : @see
2970 : @ref url,
2971 : @ref url_view.
2972 : */
2973 : system::result<void>
2974 : resolve(
2975 : url_view_base const& ref);
2976 :
2977 : friend
2978 : system::result<void>
2979 : resolve(
2980 : url_view_base const& base,
2981 : url_view_base const& ref,
2982 : url_base& dest);
2983 :
2984 : private:
2985 : //--------------------------------------------
2986 : //
2987 : // implementation
2988 : //
2989 : //--------------------------------------------
2990 :
2991 : void check_invariants() const noexcept;
2992 :
2993 : char* resize_impl(int, std::size_t, op_t&);
2994 : char* resize_impl(int, int, std::size_t, op_t&);
2995 : char* shrink_impl(int, std::size_t, op_t&);
2996 : char* shrink_impl(int, int, std::size_t, op_t&);
2997 :
2998 : void set_scheme_impl(core::string_view, urls::scheme);
2999 : char* set_user_impl(std::size_t n, op_t& op);
3000 : char* set_password_impl(std::size_t n, op_t& op);
3001 : char* set_userinfo_impl(std::size_t n, op_t& op);
3002 : char* set_host_impl(std::size_t n, op_t& op);
3003 : char* set_port_impl(std::size_t n, op_t& op);
3004 : char* set_path_impl(std::size_t n, op_t& op);
3005 :
3006 : void
3007 : set_host_ipv6_and_zone_id(
3008 : ipv6_address const& addr,
3009 : core::string_view zone_id);
3010 :
3011 : void
3012 : set_host_ipv6_and_encoded_zone_id(
3013 : ipv6_address const& addr,
3014 : pct_string_view zone_id);
3015 :
3016 : core::string_view
3017 : first_segment() const noexcept;
3018 :
3019 : detail::segments_iter_impl
3020 : edit_segments(
3021 : detail::segments_iter_impl const&,
3022 : detail::segments_iter_impl const&,
3023 : detail::any_segments_iter&& it0,
3024 : int absolute = -1);
3025 :
3026 : auto
3027 : edit_params(
3028 : detail::params_iter_impl const&,
3029 : detail::params_iter_impl const&,
3030 : detail::any_params_iter&&) ->
3031 : detail::params_iter_impl;
3032 :
3033 : // Decode any unnecessary percent-escapes
3034 : // and ensures hexadecimals are uppercase.
3035 : // The encoding of ignored characters is
3036 : // preserved.
3037 : template
3038 : <class AllowedCharSet,
3039 : class IgnoredCharSet>
3040 : void
3041 : normalize_octets_impl(
3042 : int,
3043 : AllowedCharSet const& allowed,
3044 : IgnoredCharSet const& ignored,
3045 : op_t&) noexcept;
3046 :
3047 : template<class CharSet>
3048 : void
3049 : normalize_octets_impl(
3050 : int,
3051 : CharSet const& allowed,
3052 : op_t&) noexcept;
3053 :
3054 : void decoded_to_lower_impl(int id) noexcept;
3055 : void to_lower_impl(int id) noexcept;
3056 : };
3057 :
3058 : //------------------------------------------------
3059 :
3060 : /** Resolve a URL reference against a base URL
3061 :
3062 : This function attempts to resolve a URL
3063 : reference `ref` against the base URL `base`
3064 : in a manner similar to that of a web browser
3065 : resolving an anchor tag.
3066 :
3067 : The base URL must satisfy the <em>URI</em>
3068 : grammar. In other words, it must contain
3069 : a scheme.
3070 :
3071 : Relative references are only usable when
3072 : in the context of a base absolute URI.
3073 : This process of resolving a relative
3074 : <em>reference</em> within the context of
3075 : a <em>base</em> URI is defined in detail
3076 : in rfc3986 (see below).
3077 :
3078 : The resolution process works as if the
3079 : relative reference is appended to the base
3080 : URI and the result is normalized.
3081 :
3082 : Given the input base URL, this function
3083 : resolves the relative reference
3084 : as if performing the following steps:
3085 :
3086 : @li Ensure the base URI has at least a scheme
3087 : @li Normalizing the reference path
3088 : @li Merge base and reference paths
3089 : @li Normalize the merged path
3090 :
3091 : This function places the result of the
3092 : resolution into `dest`, which can be
3093 : any of the url containers that inherit
3094 : from @ref url_base.
3095 :
3096 : If an error occurs, the contents of
3097 : `dest` is unspecified and `ec` is set.
3098 :
3099 : @note Abnormal hrefs where the number of ".."
3100 : segments exceeds the number of segments in
3101 : the base path are handled by including the
3102 : unmatched ".." segments in the result, as described
3103 : in <a href="https://www.rfc-editor.org/errata/eid4547"
3104 : >Errata 4547</a>.
3105 :
3106 : @par Example
3107 : @code
3108 : url dest;
3109 : system::error_code ec;
3110 :
3111 : resolve("/one/two/three", "four", dest, ec);
3112 : assert( dest.str() == "/one/two/four" );
3113 :
3114 : resolve("http://example.com/", "/one", dest, ec);
3115 : assert( dest.str() == "http://example.com/one" );
3116 :
3117 : resolve("http://example.com/one", "/two", dest, ec);
3118 : assert( dest.str() == "http://example.com/two" );
3119 :
3120 : resolve("http://a/b/c/d;p?q", "g#s", dest, ec);
3121 : assert( dest.str() == "http://a/b/c/g#s" );
3122 : @endcode
3123 :
3124 : @par BNF
3125 : @code
3126 : absolute-URI = scheme ":" hier-part [ "?" query ]
3127 : @endcode
3128 :
3129 : @par Exception Safety
3130 : Basic guarantee.
3131 : Calls to allocate may throw.
3132 :
3133 : @return An empty `boost::system::result` upon success,
3134 : otherwise an error code if `!base.has_scheme()`.
3135 :
3136 : @param base The base URL to resolve against.
3137 :
3138 : @param ref The URL reference to resolve.
3139 :
3140 : @param dest The container where the result
3141 : is written, upon success.
3142 :
3143 : @par Specification
3144 : <a href="https://datatracker.ietf.org/doc/html/rfc3986#section-5"
3145 : >5. Reference Resolution (rfc3986)</a>
3146 :
3147 : @see
3148 : @ref url,
3149 : @ref url_view.
3150 : */
3151 : inline
3152 : system::result<void>
3153 407 : resolve(
3154 : url_view_base const& base,
3155 : url_view_base const& ref,
3156 : url_base& dest)
3157 : {
3158 407 : if (&dest != &base)
3159 406 : dest.copy(base);
3160 407 : return dest.resolve(ref);
3161 : }
3162 :
3163 : } // urls
3164 : } // boost
3165 :
3166 : // These are here because of circular references
3167 : #include <boost/url/impl/url_base.hpp>
3168 : #include <boost/url/impl/params_ref.hpp>
3169 : #include <boost/url/impl/params_encoded_ref.hpp>
3170 : #include <boost/url/impl/segments_ref.hpp>
3171 : #include <boost/url/impl/segments_encoded_ref.hpp>
3172 :
3173 : #endif
|