userver: userver/http/url.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
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
123MakeUrl(std::string_view path, std::initializer_list<std::pair<std::string_view, std::string_view>> query_args);
124
125/// @brief Make an URL with query arguments
126/// @param path Base URL path
127/// @param query_args vector of query parameters as key-value pairs
128/// @returns Complete URL with query string
129std::string
130MakeUrl(std::string_view path, const std::vector<std::pair<std::string_view, std::string_view>>& query_args);
131
132/// @brief Make a path from a template and arguments
133/// @param path Template string with placeholders in format {name}
134/// @param path_args Map of placeholder names to their values
135/// @returns Formatted path or std::nullopt if formatting fails (e.g., missing placeholder,
136/// invalid format, or empty key in path_args)
137/// @code
138/// auto url = MakeUrlWithPathArgs("/api/v1/users/{user_id}", {{"user_id", "123"}});
139/// // Returns: "/api/v1/users/123"
140/// @endcode
141std::optional<std::string> MakeUrlWithPathArgs(std::string_view path, const PathArgs& path_args);
142
143/// @brief Make an URL with path parameters and query arguments
144/// @param path Template string with placeholders in format {name}
145/// @param path_args Map of placeholder names to their values
146/// @param query_args Map of query parameters
147/// @returns Formatted URL or std::nullopt if path formatting fails
148/// @code
149/// auto url = MakeUrlWithPathArgs("/api/v1/users/{user_id}",
150/// {{"user_id", "123"}},
151/// http::Args{{"filter", "active"}});
152/// // Returns: "/api/v1/users/123?filter=active"
153/// @endcode
154std::optional<std::string>
155MakeUrlWithPathArgs(std::string_view path, const PathArgs& path_args, const Args& query_args);
156
157/// @brief Make an URL with path parameters and query arguments
158/// @param path Template string with placeholders in format {name}
159/// @param path_args Map of placeholder names to their values
160/// @param query_args Map of query parameters
161/// @returns Formatted URL or std::nullopt if path formatting fails
162/// @code
163/// auto url = MakeUrlWithPathArgs("/api/v1/users/{user_id}",
164/// {{"user_id", "123"}},
165/// std::unordered_map<std::string, std::string>{{"page", "1"}});
166/// // Returns: "/api/v1/users/123?page=1"
167/// @endcode
168std::optional<std::string> MakeUrlWithPathArgs(
169 std::string_view path,
170 const PathArgs& path_args,
171 const std::unordered_map<std::string, std::string>& query_args
172);
173
174/// @brief Make an URL with path parameters and query arguments, supporting multiple values for the same key
175/// @param path Template string with placeholders in format {name}
176/// @param path_args Map of placeholder names to their values
177/// @param query_args Map of query parameters
178/// @param query_multiargs Multimap for query parameters that can have multiple values
179/// @returns Formatted URL or std::nullopt if path formatting fails
180/// @code
181/// http::MultiArgs multi_args = {{"tag", "new"}, {"tag", "featured"}};
182/// auto url = MakeUrlWithPathArgs("/api/v1/products/{category}",
183/// {{"category", "electronics"}},
184/// http::Args{{"sort", "price"}},
185/// multi_args);
186/// // Returns: "/api/v1/products/electronics?sort=price&tag=new&tag=featured"
187/// @endcode
188std::optional<std::string> MakeUrlWithPathArgs(
189 std::string_view path,
190 const PathArgs& path_args,
191 const Args& query_args,
192 MultiArgs query_multiargs
193);
194
195/// @brief Make an URL with path parameters and query arguments
196/// @param path Template string with placeholders in format {name}
197/// @param path_args Map of placeholder names to their values
198/// @param query_args Initializer list of query parameters as key-value pairs
199/// @returns Formatted URL or std::nullopt if path formatting fails
200/// @code
201/// auto url = MakeUrlWithPathArgs("/api/v1/search/{term}",
202/// {{"term", "laptop"}},
203/// {{"brand", "apple"}, {"price_max", "2000"}});
204/// // Returns: "/api/v1/search/laptop?brand=apple&price_max=2000"
205/// @endcode
206std::optional<std::string> MakeUrlWithPathArgs(
207 std::string_view path,
208 const PathArgs& path_args,
209 std::initializer_list<std::pair<std::string_view, std::string_view>> query_args
210);
211
212/// @brief Returns URL part before the first '?' character
213/// @param url Full URL to extract from
214/// @returns URL without query string
215/// @code
216/// auto base = ExtractMetaTypeFromUrl("https://example.com/api/users?page=1&sort=name");
217/// // Returns: "https://example.com/api/users"
218/// @endcode
219std::string ExtractMetaTypeFromUrl(std::string_view url);
220std::string_view ExtractMetaTypeFromUrlView(std::string_view url);
221
222// TODO: rename to ExtractPathAndQuery()
223/// @brief Returns HTTP path part of a URL
224/// @param url Full URL to extract from
225/// @returns Path component of the URL
226/// @code
227/// auto path = ExtractPath("https://example.com/api/users");
228/// // Returns: "/api/users"
229/// auto path2 = ExtractPath("example.com/api/users?a=b");
230/// // Returns: "/api/users?a=b"
231/// @endcode
232std::string ExtractPath(std::string_view url);
233std::string_view ExtractPathView(std::string_view url);
234
235/// @brief Returns HTTP path part of a URL
236/// @param url Full URL to extract from
237/// @returns Path component of the URL
238/// @code
239/// auto path = ExtractPath("https://example.com/api/users");
240/// // Returns: "/api/users"
241/// auto path2 = ExtractPath("example.com/api/users?a=b");
242/// // Returns: "/api/users"
243/// @endcode
244std::string ExtractPathOnly(std::string_view url);
245
246/// @brief Returns hostname part of a URL
247/// @param url Full URL to extract from
248/// @returns Hostname component of the URL
249/// @code
250/// auto host = ExtractHostname("https://example.com/api/users");
251/// // Returns: "example.com"
252/// auto host2 = ExtractHostname("https://user:pass@example.com:8080/api");
253/// // Returns: "example.com"
254/// auto host3 = ExtractHostname("http://[::1]:8080/");
255/// // Returns: "[::1]"
256/// @endcode
257std::string ExtractHostname(std::string_view url);
258std::string_view ExtractHostnameView(std::string_view url);
259
260/// @brief Returns scheme part of a URL
261/// @param url Full URL to extract from
262/// @returns Scheme component of the URL
263/// @code
264/// auto scheme = ExtractScheme("https://example.com/api/users");
265/// // Returns: "https"
266/// auto scheme2 = ExtractScheme("http://user:pass@example.com:8080/api");
267/// // Returns: "http"
268/// auto scheme3 = ExtractScheme("ftp://[::1]:8080/");
269/// // Returns: "ftp"
270/// @endcode
271std::string ExtractScheme(std::string_view url);
272std::string_view ExtractSchemeView(std::string_view url);
273
274/// @brief Returns query part of a URL
275/// @param url Full URL to extract from
276/// @returns Query component of the URL
277/// @code
278/// auto query = ExtractQuery("https://example.com/api/users?q=1");
279/// // Returns: "q=1"
280/// auto query2 = ExtractQuery("http://user:pass@example.com:8080/api");
281/// // Returns: ""
282/// auto query3 = ExtractQuery("ftp://[::1]:8080/?q=12&w=23");
283/// // Returns: "q=12&w=23"
284/// @endcode
285std::string ExtractQuery(std::string_view url);
286std::string_view ExtractQueryView(std::string_view url);
287
288/// @brief Returns fragment part of a URL
289/// @param url Full URL to extract from
290/// @returns Fragment component of the URL
291/// @code
292/// auto fragment = ExtractFragment("https://example.com/api/users?q=1");
293/// // Returns: ""
294/// auto fragment2 = ExtractFragment("http://user:pass@example.com:8080/api#123");
295/// // Returns: "123"
296/// auto fragment3 = ExtractFragment("ftp://[::1]:8080/#123?q=12&w=23");
297/// // Returns: "123"
298/// auto fragment4 = ExtractFragment("ftp://[::1]:8080/?q=12&w=23#123");
299/// // Returns: "123"
300/// @endcode
301std::string ExtractFragment(std::string_view url);
302std::string_view ExtractFragmentView(std::string_view url);
303
304/// @brief Returns decomposed URL as a struct,
305/// broken into main parts: scheme, host, path, query, and fragment
307
308namespace impl {
309
310std::string UrlDecode(utils::impl::InternalTag, std::string_view range);
311
312} // namespace impl
313
314} // namespace http
315
316USERVER_NAMESPACE_END