1 | /* |
2 | * Copyright 2013-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #pragma once |
18 | #define FOLLY_URI_H_ |
19 | |
20 | #include <string> |
21 | #include <vector> |
22 | |
23 | #include <folly/String.h> |
24 | |
25 | namespace folly { |
26 | |
27 | /** |
28 | * Class representing a URI. |
29 | * |
30 | * Consider http://www.facebook.com/foo/bar?key=foo#anchor |
31 | * |
32 | * The URI is broken down into its parts: scheme ("http"), authority |
33 | * (ie. host and port, in most cases: "www.facebook.com"), path |
34 | * ("/foo/bar"), query ("key=foo") and fragment ("anchor"). The scheme is |
35 | * lower-cased. |
36 | * |
37 | * If this Uri represents a URL, note that, to prevent ambiguity, the component |
38 | * parts are NOT percent-decoded; you should do this yourself with |
39 | * uriUnescape() (for the authority and path) and uriUnescape(..., |
40 | * UriEscapeMode::QUERY) (for the query, but probably only after splitting at |
41 | * '&' to identify the individual parameters). |
42 | */ |
43 | class Uri { |
44 | public: |
45 | /** |
46 | * Parse a Uri from a string. Throws std::invalid_argument on parse error. |
47 | */ |
48 | explicit Uri(StringPiece str); |
49 | |
50 | const std::string& scheme() const { |
51 | return scheme_; |
52 | } |
53 | const std::string& username() const { |
54 | return username_; |
55 | } |
56 | const std::string& password() const { |
57 | return password_; |
58 | } |
59 | /** |
60 | * Get host part of URI. If host is an IPv6 address, square brackets will be |
61 | * returned, for example: "[::1]". |
62 | */ |
63 | const std::string& host() const { |
64 | return host_; |
65 | } |
66 | /** |
67 | * Get host part of URI. If host is an IPv6 address, square brackets will not |
68 | * be returned, for exmaple "::1"; otherwise it returns the same thing as |
69 | * host(). |
70 | * |
71 | * hostname() is what one needs to call if passing the host to any other tool |
72 | * or API that connects to that host/port; e.g. getaddrinfo() only understands |
73 | * IPv6 host without square brackets |
74 | */ |
75 | std::string hostname() const; |
76 | uint16_t port() const { |
77 | return port_; |
78 | } |
79 | const std::string& path() const { |
80 | return path_; |
81 | } |
82 | const std::string& query() const { |
83 | return query_; |
84 | } |
85 | const std::string& fragment() const { |
86 | return fragment_; |
87 | } |
88 | |
89 | std::string authority() const; |
90 | |
91 | template <class String> |
92 | String toString() const; |
93 | |
94 | std::string str() const { |
95 | return toString<std::string>(); |
96 | } |
97 | fbstring fbstr() const { |
98 | return toString<fbstring>(); |
99 | } |
100 | |
101 | void setPort(uint16_t port) { |
102 | hasAuthority_ = true; |
103 | port_ = port; |
104 | } |
105 | |
106 | /** |
107 | * Get query parameters as key-value pairs. |
108 | * e.g. for URI containing query string: key1=foo&key2=&key3&=bar&=bar= |
109 | * In returned list, there are 3 entries: |
110 | * "key1" => "foo" |
111 | * "key2" => "" |
112 | * "key3" => "" |
113 | * Parts "=bar" and "=bar=" are ignored, as they are not valid query |
114 | * parameters. "=bar" is missing parameter name, while "=bar=" has more than |
115 | * one equal signs, we don't know which one is the delimiter for key and |
116 | * value. |
117 | * |
118 | * Note, this method is not thread safe, it might update internal state, but |
119 | * only the first call to this method update the state. After the first call |
120 | * is finished, subsequent calls to this method are thread safe. |
121 | * |
122 | * @return query parameter key-value pairs in a vector, each element is a |
123 | * pair of which the first element is parameter name and the second |
124 | * one is parameter value |
125 | */ |
126 | const std::vector<std::pair<std::string, std::string>>& getQueryParams(); |
127 | |
128 | private: |
129 | std::string scheme_; |
130 | std::string username_; |
131 | std::string password_; |
132 | std::string host_; |
133 | bool hasAuthority_; |
134 | uint16_t port_; |
135 | std::string path_; |
136 | std::string query_; |
137 | std::string fragment_; |
138 | std::vector<std::pair<std::string, std::string>> queryParams_; |
139 | }; |
140 | |
141 | } // namespace folly |
142 | |
143 | #include <folly/Uri-inl.h> |
144 | |