HTTP v1.17.0
Loading...
Searching...
No Matches
HttpBuilder.cpp
Go to the documentation of this file.
1#include "HttpBuilder.h"
2
3#include <array>
4#include <unordered_map>
5#include <unordered_set>
6#include <algorithm>
7
8#include "HttpParser.h"
9
10static const std::unordered_set<std::string_view> availableHTTPVersions =
11{
12 "HTTP/0.9",
13 "HTTP/1.0",
14 "HTTP/1.1"
15};
16
17namespace web
18{
19 std::string HttpBuilder::getChunks(const std::vector<std::string>& chunks, bool partialChunks, bool preCalculateSize)
20 {
21 std::string result;
22
23 if (preCalculateSize)
24 {
25 size_t resultSize = 0;
26
27 for (const std::string& chunk : chunks)
28 {
29 resultSize += std::format("{:x}", chunk.size()).size() + constants::crlf.size() + chunk.size() + constants::crlf.size();
30 }
31
32 resultSize += 1 + constants::crlf.size();
33
34 result.reserve(resultSize);
35 }
36
37 for (const std::string& chunk : chunks)
38 {
39 result += HttpBuilder::getChunk(chunk);
40 }
41
42 if (!partialChunks)
43 {
44 result += HttpBuilder::getChunk({});
45 }
46
47 return result;
48 }
49
50 std::string HttpBuilder::getChunk(std::string_view chunk)
51 {
52 return std::format("{:x}{}{}{}", chunk.size(), constants::crlf, chunk, constants::crlf);
53 }
54
55 HttpBuilder::HttpBuilder(std::string_view fullHTTPVersion) :
56 _HTTPVersion(fullHTTPVersion),
57 _partialChunks(false)
58 {
59 if (availableHTTPVersions.find(_HTTPVersion) == availableHTTPVersions.end())
60 {
61 throw std::runtime_error(std::format("HTTP version: {} not supported", _HTTPVersion));
62 }
63 }
64
65 HttpBuilder& HttpBuilder::getRequest()
66 {
67 method = "GET";
68
69 return *this;
70 }
71
72 HttpBuilder& HttpBuilder::postRequest()
73 {
74 method = "POST";
75
76 return *this;
77 }
78
79 HttpBuilder& HttpBuilder::putRequest()
80 {
81 method = "PUT";
82
83 return *this;
84 }
85
86 HttpBuilder& HttpBuilder::headRequest()
87 {
88 method = "HEAD";
89
90 return *this;
91 }
92
93 HttpBuilder& HttpBuilder::optionsRequest()
94 {
95 method = "OPTIONS";
96
97 return *this;
98 }
99
100 HttpBuilder& HttpBuilder::deleteRequest()
101 {
102 method = "DELETE";
103
104 return *this;
105 }
106
107 HttpBuilder& HttpBuilder::connectRequest()
108 {
109 method = "CONNECT";
110
111 return *this;
112 }
113
114 HttpBuilder& HttpBuilder::traceRequest()
115 {
116 method = "TRACE";
117
118 return *this;
119 }
120
121 HttpBuilder& HttpBuilder::patchRequest()
122 {
123 method = "PATCH";
124
125 return *this;
126 }
127
128 HttpBuilder& HttpBuilder::parameters(std::string_view parameters)
129 {
130 if (method != "CONNECT")
131 {
132 if (size_t queryStart = parameters.find('?'); queryStart != std::string::npos)
133 {
134 _parameters = std::format
135 (
136 "{}{}",
137 std::string_view(parameters.begin(), parameters.begin() + queryStart + 1),
138 std::string_view(parameters.begin() + queryStart + 1, parameters.end())
139 );
140 }
141 else
142 {
143 _parameters = parameters;
144 }
145
146 if (!_parameters.starts_with('/'))
147 {
148 _parameters.insert(_parameters.begin(), '/');
149 }
150 }
151 else
152 {
153 _parameters = parameters;
154 }
155
156 return *this;
157 }
158
159 HttpBuilder& HttpBuilder::responseCode(ResponseCodes code)
160 {
161 _responseCode = format("{} {}", static_cast<int>(code), getMessageFromCode(code));
162
163 return *this;
164 }
165
166 HttpBuilder& HttpBuilder::responseCode(int code, std::string_view responseMessage)
167 {
168 _responseCode = format("{} {}", code, responseMessage);
169
170 return *this;
171 }
172
173 HttpBuilder& HttpBuilder::HTTPVersion(std::string_view HTTPVersion)
174 {
175 if (HTTPVersion.find("HTTP") == std::string::npos)
176 {
177 _HTTPVersion = HTTPVersion;
178 }
179 else
180 {
181 _HTTPVersion = std::format("HTTP/{}", HTTPVersion);
182 }
183
184 if (availableHTTPVersions.find(_HTTPVersion) == availableHTTPVersions.end())
185 {
186 throw std::runtime_error(std::format("HTTP version: {} not supported", _HTTPVersion));
187 }
188
189 return *this;
190 }
191
192 HttpBuilder& HttpBuilder::chunks(const std::vector<std::string>& chunks)
193 {
194 _chunks.reserve(chunks.size());
195
196 copy(chunks.begin(), chunks.end(), back_inserter(_chunks));
197
198 return *this;
199 }
200
201 HttpBuilder& HttpBuilder::chunks(std::vector<std::string>&& chunks)
202 {
203 _chunks.reserve(chunks.size());
204
205 move(chunks.begin(), chunks.end(), back_inserter(_chunks));
206
207 return *this;
208 }
209
210 HttpBuilder& HttpBuilder::chunk(std::string_view chunk)
211 {
212 _chunks.emplace_back(chunk);
213
214 return *this;
215 }
216
217 HttpBuilder& HttpBuilder::clear()
218 {
219 method.clear();
220 _parameters.clear();
221 _responseCode.clear();
222 _headers.clear();
223
224 return *this;
225 }
226
227 HttpBuilder& HttpBuilder::partialChunks()
228 {
229 _partialChunks = true;
230
231 return *this;
232 }
233
234 std::ostream& operator << (std::ostream& outputStream, const HttpBuilder& builder)
235 {
236 return outputStream << builder.build();
237 }
238}
std::ostream & operator<<(std::ostream &outputStream, const HttpBuilder &builder)