HTTP v1.13.1
Loading...
Searching...
No Matches
HTTPBuilder.h
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4#include <stdexcept>
5#include <format>
6#include <concepts>
7
8#include "HTTPUtility.h"
10#include "JSONBuilder.h"
11
12namespace web
13{
16 {
17 private:
18 std::string method;
19 std::string _parameters;
20 std::string _responseCode;
21 std::string _headers;
22 std::string _HTTPVersion;
23 std::vector<std::string> _chunks;
24 bool _partialChunks;
25
26 public:
32 static std::string getChunks(const std::vector<std::string>& chunks, bool partialChunks, bool preCalculateSize = false);
33
37 static std::string getChunk(std::string_view chunk);
38
39 public:
40 HTTPBuilder(std::string_view fullHTTPVersion = "HTTP/1.1");
41
42 HTTPBuilder(const HTTPBuilder& other) = default;
43
44 HTTPBuilder(HTTPBuilder&& other) noexcept = default;
45
46 HTTPBuilder& operator = (const HTTPBuilder& other) = default;
47
48 HTTPBuilder& operator = (HTTPBuilder&& other) noexcept = default;
49
52 HTTPBuilder& getRequest();
53
56 HTTPBuilder& postRequest();
57
60 HTTPBuilder& putRequest();
61
64 HTTPBuilder& headRequest();
65
68 HTTPBuilder& optionsRequest();
69
72 HTTPBuilder& deleteRequest();
73
76 HTTPBuilder& connectRequest();
77
80 HTTPBuilder& traceRequest();
81
84 HTTPBuilder& patchRequest();
85
94 template<typename StringT, typename T, typename... Args>
95 HTTPBuilder& queryParameters(StringT&& name, T&& value, Args&&... args);
96
97 template<typename... Args>
98 HTTPBuilder& parametersWithRoute(std::string_view route, Args&&... args);
99
103 HTTPBuilder& parameters(std::string_view parameters);
104
105 HTTPBuilder& responseCode(ResponseCodes code);
106
107 HTTPBuilder& responseCode(int code, std::string_view responseMessage);
108
109 HTTPBuilder& HTTPVersion(std::string_view httpVersion);
110
119 template<typename StringT, typename T, typename... Args>
120 HTTPBuilder& headers(StringT&& name, T&& value, Args&&... args);
121
122 HTTPBuilder& chunks(const std::vector<std::string>& chunks);
123
124 HTTPBuilder& chunks(std::vector<std::string>&& chunks);
125
126 HTTPBuilder& chunk(std::string_view chunk);
127
128 std::string build(std::string_view data = "", const std::unordered_map<std::string, std::string>& additionalHeaders = {}) const;
129
130 std::string build(const json::JSONBuilder& builder, std::unordered_map<std::string, std::string> additionalHeaders = {}) const;
131
132 std::string build(const std::unordered_map<std::string, std::string>& urlEncoded, std::unordered_map<std::string, std::string> additionalHeaders = {}) const;
133
134 HTTPBuilder& clear();
135
136 HTTPBuilder& partialChunks();
137
142 friend HTTP_API std::ostream& operator << (std::ostream& outputStream, const HTTPBuilder& builder);
143
144 ~HTTPBuilder() = default;
145 };
146
147 template<typename StringT, typename T, typename... Args>
148 HTTPBuilder& HTTPBuilder::queryParameters(StringT&& name, T&& value, Args&&... args)
149 {
150 static_assert(std::is_convertible_v<decltype(name), std::string_view>, "Wrong StringT type");
151
152 if (_parameters.empty())
153 {
154 _parameters = "/?";
155 }
156
157 if constexpr (std::is_arithmetic_v<T>)
158 {
159 _parameters += std::format("{}={}&", web::encodeUrl(static_cast<std::string_view>(name)), std::to_string(value));
160 }
161 else if constexpr (std::is_convertible_v<decltype(value), std::string_view>)
162 {
163 _parameters += std::format("{}={}&", web::encodeUrl(static_cast<std::string_view>(name)), web::encodeUrl(static_cast<std::string_view>(value)));
164 }
165 else if constexpr (std::is_convertible_v<decltype(value), std::string>)
166 {
167 _parameters += std::format("{}={}&", web::encodeUrl(static_cast<std::string_view>(name)), web::encodeUrl(static_cast<std::string>(value)));
168 }
169 else
170 {
171 throw std::logic_error("Bad type of T, it must be converted to string or arithmetic type");
172 }
173
174 if constexpr (requires { std::invocable<decltype(&HTTPBuilder::queryParameters<Args...>), decltype(this), Args...>; })
175 {
176 return this->queryParameters(std::forward<Args>(args)...);
177 }
178
179 _parameters.pop_back(); // remove '&'
180
181 return *this;
182 }
183
184 template<typename... Args>
185 HTTPBuilder& HTTPBuilder::parametersWithRoute(std::string_view route, Args&&... args)
186 {
187 if (route.starts_with('/'))
188 {
189 _parameters = route;
190 }
191 else
192 {
193 _parameters = "/";
194
195 _parameters += route;
196 }
197
198 if (!route.ends_with('?'))
199 {
200 _parameters += '?';
201 }
202
203 return this->queryParameters(std::forward<Args>(args)...);
204 }
205
206 template<typename StringT, typename T, typename... Args>
207 HTTPBuilder& HTTPBuilder::headers(StringT&& name, T&& value, Args&&... args)
208 {
210 {
211 if constexpr (sizeof...(args))
212 {
213 if (static_cast<std::string>(name) == "Content-Length" || static_cast<std::string>(name) == "content-length")
214 {
215 return headers(std::forward<Args>(args)...);
216 }
217 }
218
219 if constexpr (std::is_arithmetic_v<std::remove_reference_t<T>>)
220 {
221 _headers += static_cast<std::string>(name) + std::string(": ") + std::to_string(value) + std::string("\r\n");
222 }
224 {
225 _headers += static_cast<std::string>(name) + std::string(": ") + static_cast<std::string>(value) + std::string("\r\n");
226 }
228 {
229 _headers += static_cast<std::string>(name) + std::string(": ");
230
231 auto checkValueType = *std::begin(value);
232
233 if constexpr (std::is_arithmetic_v<decltype(checkValueType)>)
234 {
235 for (auto&& i : value)
236 {
237 _headers += std::to_string(i) + std::string(", ");
238 }
239
240 _headers.pop_back(); // delete space
241 _headers.pop_back(); // delete ;
242
243 _headers.insert(_headers.size(), "\r\n");
244 }
245 else if constexpr (::utility::StringConversion<decltype(checkValueType)>::value)
246 {
247 for (auto&& i : value)
248 {
249 _headers += static_cast<std::string>(i) + std::string(", ");
250 }
251
252 _headers.pop_back(); // delete space
253 _headers.pop_back(); // delete ;
254
255 _headers.insert(_headers.size(), "\r\n");
256 }
257 else
258 {
259 throw std::logic_error("Bad type of values in class T, it must be converted to string or arithmetic type");
260 }
261 }
262 else
263 {
264 throw std::logic_error("Bad type of T, it must be converted to string or arithmetic type");
265 }
266 }
267 else
268 {
269 throw std::logic_error("Bad type of StringT, it must be converted to string");
270 }
271
272 if constexpr (sizeof...(args))
273 {
274 return headers(std::forward<Args>(args)...);
275 }
276
277 return *this;
278 }
279}
#define HTTP_API
Definition HTTPUtility.h:17
HTTP builder.
Definition HTTPBuilder.h:16
std::string build(const std::unordered_map< std::string, std::string > &urlEncoded, std::unordered_map< std::string, std::string > additionalHeaders={}) const
HTTPBuilder & responseCode(int code, std::string_view responseMessage)
HTTPBuilder(const HTTPBuilder &other)=default
HTTPBuilder & headers(StringT &&name, T &&value, Args &&... args)
Append header - value.
HTTPBuilder & queryParameters(StringT &&name, T &&value, Args &&... args)
Append key - value parameters.
HTTPBuilder & parametersWithRoute(std::string_view route, Args &&... args)
HTTPBuilder(HTTPBuilder &&other) noexcept=default
HTTPBuilder(std::string_view fullHTTPVersion="HTTP/1.1")
std::string build(const json::JSONBuilder &builder, std::unordered_map< std::string, std::string > additionalHeaders={}) const
~HTTPBuilder()=default
std::string build(std::string_view data="", const std::unordered_map< std::string, std::string > &additionalHeaders={}) const
HTTPBuilder & chunks(std::vector< std::string > &&chunks)
HTTPBuilder & chunks(const std::vector< std::string > &chunks)
ResponseCodes
Response codes.
Definition HTTPUtility.h:25
string encodeUrl(string_view data)