userver: userver/http/url.hpp Source File
Loading...
Searching...
No Matches
url.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/http/url.hpp
4/// @brief URL manipulation functions
5/// @ingroup userver_universal
6
7#include <map>
8#include <optional>
9#include <string>
10#include <string_view>
11#include <unordered_map>
12#include <vector>
13
14#include <userver/utils/impl/internal_tag_fwd.hpp>
15#include <userver/utils/str_icase.hpp>
16
17USERVER_NAMESPACE_BEGIN
18
19namespace http {
20
22 std::string_view scheme;
23 std::string_view host;
24 std::string_view path;
25 std::string_view query;
26 std::string_view fragment;
27};
28
29/// @brief Decode URL
30[[deprecated("Use a more strict http::parser::UrlDecode instead")]] std::string UrlDecode(std::string_view range);
31
32/// @brief Encode as URL
33/// @param input_string String to encode
34/// @returns URL-encoded string where special characters are encoded as %XX sequences
35/// @code
36/// auto encoded = UrlEncode("hello world");
37/// // Returns: "hello%20world"
38/// @endcode
39std::string UrlEncode(std::string_view input_string);
40
41using Args = std::unordered_map<std::string, std::string, utils::StrCaseHash>;
42using MultiArgs = std::multimap<std::string, std::string>;
43using PathArgs = std::unordered_map<std::string, std::string>;
44
45/// @brief Make an URL query
46/// @param query_args Map of query parameters
47/// @returns URL query string without leading '?' character
48/// @code
49/// auto query = MakeQuery(http::Args{{"param", "value"}, {"filter", "active"}});
50/// // Returns: "param=value&filter=active"
51/// @endcode
52std::string MakeQuery(const Args& query_args);
53
54/// @brief Make an URL query
55/// @param query_args Multimap of query parameters
56/// @returns URL query string without leading '?' character
57/// @code
58/// http::MultiArgs args = {{"tag", "new"}, {"tag", "featured"}};
59/// auto query = MakeQuery(args);
60/// // Returns: "tag=new&tag=featured"
61/// @endcode
62std::string MakeQuery(const MultiArgs& query_args);
63
64/// @brief Make an URL query
65/// @param query_args Map of query parameters
66/// @returns URL query string without leading '?' character
67/// @code
68/// auto query = MakeQuery(std::unordered_map<std::string, std::string>{{"page", "1"}, {"size", "10"}});
69/// // Returns: "page=1&size=10"
70/// @endcode
71std::string MakeQuery(const std::unordered_map<std::string, std::string>& query_args);
72
73/// @brief Make an URL query
74/// @param query_args Initializer list of query parameters as key-value pairs
75/// @returns URL query string without leading '?' character
76/// @code
77/// auto query = MakeQuery({{"sort", "date"}, {"order", "desc"}});
78/// // Returns: "sort=date&order=desc"
79/// @endcode
80std::string MakeQuery(std::initializer_list<std::pair<std::string_view, std::string_view>> query_args);
81
82/// @brief Make an URL with query arguments
83/// @param path Base URL path
84/// @param query_args Map of query parameters
85/// @returns Complete URL with query string
86/// @code
87/// auto url = MakeUrl("/api/users", http::Args{{"status", "active"}});
88/// // Returns: "/api/users?status=active"
89/// @endcode
90std::string MakeUrl(std::string_view path, const Args& query_args);
91
92/// @brief Make an URL with query arguments
93/// @param path Base URL path
94/// @param query_args Map of query parameters
95/// @returns Complete URL with query string
96/// @code
97/// auto url = MakeUrl("/api/products", std::unordered_map<std::string, std::string>{{"category", "electronics"}});
98/// // Returns: "/api/products?category=electronics"
99/// @endcode
100std::string MakeUrl(std::string_view path, const std::unordered_map<std::string, std::string>& query_args);
101
102/// @brief Make an URL with query arguments
103/// @param path Base URL path
104/// @param query_args Map of query parameters
105/// @param query_multiargs Multimap for query parameters that can have multiple values
106/// @returns Complete URL with query string
107/// @code
108/// http::MultiArgs multi_args = {{"tag", "new"}, {"tag", "featured"}};
109/// auto url = MakeUrl("/api/products", http::Args{{"category", "electronics"}}, multi_args);
110/// // Returns: "/api/products?category=electronics&tag=new&tag=featured"
111/// @endcode
112std::string MakeUrl(std::string_view path, const Args& query_args, MultiArgs query_multiargs);
113
114/// @brief Make an URL with query arguments
115/// @param path Base URL path
116/// @param query_args Initializer list of query parameters as key-value pairs
117/// @returns Complete URL with query string
118/// @code
119/// auto url = MakeUrl("/api/search", {{"q", "smartphone"}, {"sort", "relevance"}});
120/// // Returns: "/api/search?q=smartphone&sort=relevance"
121/// @endcode
122std::string MakeUrl(
123 std::string_view path,
124 std::initializer_list<std::pair<std::string_view, std::string_view>> query_args
125);
126
127/// @brief Make an URL with query arguments
128/// @param path Base URL path
129/// @param query_args vector of query parameters as key-value pairs
130/// @returns Complete URL with query string
131std::string MakeUrl(
132 std::string_view path,
133 const std::vector<std::pair<std::string_view, std::string_view>>& query_args
134);
135
136/// @brief Make a path from a template and arguments
137/// @param path Template string with placeholders in format {name}
138/// @param path_args Map of placeholder names to their values
139/// @returns Formatted path or std::nullopt if formatting fails (e.g., missing placeholder,
140/// invalid format, or empty key in path_args)
141/// @code
142/// auto url = MakeUrlWithPathArgs("/api/v1/users/{user_id}", {{"user_id", "123"}});
143/// // Returns: "/api/v1/users/123"
144/// @endcode
145std::optional<std::string> MakeUrlWithPathArgs(std::string_view path, const PathArgs& path_args);
146
147/// @brief Make an URL with path parameters and query arguments
148/// @param path Template string with placeholders in format {name}
149/// @param path_args Map of placeholder names to their values
150/// @param query_args Map of query parameters
151/// @returns Formatted URL or std::nullopt if path formatting fails
152/// @code
153/// auto url = MakeUrlWithPathArgs("/api/v1/users/{user_id}",
154/// {{"user_id", "123"}},
155/// http::Args{{"filter", "active"}});
156/// // Returns: "/api/v1/users/123?filter=active"
157/// @endcode
158std::optional<std::string> MakeUrlWithPathArgs(
159 std::string_view path,
160 const PathArgs& path_args,
161 const Args& query_args
162);
163
164/// @brief Make an URL with path parameters and query arguments
165/// @param path Template string with placeholders in format {name}
166/// @param path_args Map of placeholder names to their values
167/// @param query_args Map of query parameters
168/// @returns Formatted URL or std::nullopt if path formatting fails
169/// @code
170/// auto url = MakeUrlWithPathArgs("/api/v1/users/{user_id}",
171/// {{"user_id", "123"}},
172/// std::unordered_map<std::string, std::string>{{"page", "1"}});
173/// // Returns: "/api/v1/users/123?page=1"
174/// @endcode
175std::optional<std::string> MakeUrlWithPathArgs(
176 std::string_view path,
177 const PathArgs& path_args,
178 const std::unordered_map<std::string, std::string>& query_args
179);
180
181/// @brief Make an URL with path parameters and query arguments, supporting multiple values for the same key
182/// @param path Template string with placeholders in format {name}
183/// @param path_args Map of placeholder names to their values
184/// @param query_args Map of query parameters
185/// @param query_multiargs Multimap for query parameters that can have multiple values
186/// @returns Formatted URL or std::nullopt if path formatting fails
187/// @code
188/// http::MultiArgs multi_args = {{"tag", "new"}, {"tag", "featured"}};
189/// auto url = MakeUrlWithPathArgs("/api/v1/products/{category}",
190/// {{"category", "electronics"}},
191/// http::Args{{"sort", "price"}},
192/// multi_args);
193/// // Returns: "/api/v1/products/electronics?sort=price&tag=new&tag=featured"
194/// @endcode
195std::optional<std::string> MakeUrlWithPathArgs(
196 std::string_view path,
197 const PathArgs& path_args,
198 const Args& query_args,
199 MultiArgs query_multiargs
200);
201
202/// @brief Make an URL with path parameters and query arguments
203/// @param path Template string with placeholders in format {name}
204/// @param path_args Map of placeholder names to their values
205/// @param query_args Initializer list of query parameters as key-value pairs
206/// @returns Formatted URL or std::nullopt if path formatting fails
207/// @code
208/// auto url = MakeUrlWithPathArgs("/api/v1/search/{term}",
209/// {{"term", "laptop"}},
210/// {{"brand", "apple"}, {"price_max", "2000"}});
211/// // Returns: "/api/v1/search/laptop?brand=apple&price_max=2000"
212/// @endcode
213std::optional<std::string> MakeUrlWithPathArgs(
214 std::string_view path,
215 const PathArgs& path_args,
216 std::initializer_list<std::pair<std::string_view, std::string_view>> query_args
217);
218
219/// @brief Returns URL part before the first '?' character
220/// @param url Full URL to extract from
221/// @returns URL without query string
222/// @code
223/// auto base = ExtractMetaTypeFromUrl("https://example.com/api/users?page=1&sort=name");
224/// // Returns: "https://example.com/api/users"
225/// @endcode
226std::string ExtractMetaTypeFromUrl(std::string_view url);
227std::string_view ExtractMetaTypeFromUrlView(std::string_view url);
228
229// TODO: rename to ExtractPathAndQuery()
230/// @brief Returns HTTP path part of a URL
231/// @param url Full URL to extract from
232/// @returns Path component of the URL
233/// @code
234/// auto path = ExtractPath("https://example.com/api/users");
235/// // Returns: "/api/users"
236/// auto path2 = ExtractPath("example.com/api/users?a=b");
237/// // Returns: "/api/users?a=b"
238/// @endcode
239std::string ExtractPath(std::string_view url);
240std::string_view ExtractPathView(std::string_view url);
241
242/// @brief Returns HTTP path part of a URL
243/// @param url Full URL to extract from
244/// @returns Path component of the URL
245/// @code
246/// auto path = ExtractPath("https://example.com/api/users");
247/// // Returns: "/api/users"
248/// auto path2 = ExtractPath("example.com/api/users?a=b");
249/// // Returns: "/api/users"
250/// @endcode
251std::string ExtractPathOnly(std::string_view url);
252
253/// @brief Returns hostname part of a URL
254/// @param url Full URL to extract from
255/// @returns Hostname component of the URL
256/// @code
257/// auto host = ExtractHostname("https://example.com/api/users");
258/// // Returns: "example.com"
259/// auto host2 = ExtractHostname("https://user:pass@example.com:8080/api");
260/// // Returns: "example.com"
261/// auto host3 = ExtractHostname("http://[::1]:8080/");
262/// // Returns: "[::1]"
263/// @endcode
264std::string ExtractHostname(std::string_view url);
265std::string_view ExtractHostnameView(std::string_view url);
266
267/// @brief Returns scheme part of a URL
268/// @param url Full URL to extract from
269/// @returns Scheme component of the URL
270/// @code
271/// auto scheme = ExtractScheme("https://example.com/api/users");
272/// // Returns: "https"
273/// auto scheme2 = ExtractScheme("http://user:pass@example.com:8080/api");
274/// // Returns: "http"
275/// auto scheme3 = ExtractScheme("ftp://[::1]:8080/");
276/// // Returns: "ftp"
277/// @endcode
278std::string ExtractScheme(std::string_view url);
279std::string_view ExtractSchemeView(std::string_view url);
280
281/// @brief Returns query part of a URL
282/// @param url Full URL to extract from
283/// @returns Query component of the URL
284/// @code
285/// auto query = ExtractQuery("https://example.com/api/users?q=1");
286/// // Returns: "q=1"
287/// auto query2 = ExtractQuery("http://user:pass@example.com:8080/api");
288/// // Returns: ""
289/// auto query3 = ExtractQuery("ftp://[::1]:8080/?q=12&w=23");
290/// // Returns: "q=12&w=23"
291/// @endcode
292std::string ExtractQuery(std::string_view url);
293std::string_view ExtractQueryView(std::string_view url);
294
295/// @brief Returns fragment part of a URL
296/// @param url Full URL to extract from
297/// @returns Fragment component of the URL
298/// @code
299/// auto fragment = ExtractFragment("https://example.com/api/users?q=1");
300/// // Returns: ""
301/// auto fragment2 = ExtractFragment("http://user:pass@example.com:8080/api#123");
302/// // Returns: "123"
303/// auto fragment3 = ExtractFragment("ftp://[::1]:8080/#123?q=12&w=23");
304/// // Returns: "123"
305/// auto fragment4 = ExtractFragment("ftp://[::1]:8080/?q=12&w=23#123");
306/// // Returns: "123"
307/// @endcode
308std::string ExtractFragment(std::string_view url);
309std::string_view ExtractFragmentView(std::string_view url);
310
311/// @brief Returns decomposed URL as a struct,
312/// broken into main parts: scheme, host, path, query, and fragment
314
315namespace impl {
316
317std::string UrlDecode(utils::impl::InternalTag, std::string_view range);
318
319} // namespace impl
320
321} // namespace http
322
323USERVER_NAMESPACE_END