WebFramework v3.0.12
Web framework for C++.
Loading...
Searching...
No Matches
HTTPRequest.cpp
1#include "HTTPRequest.h"
2
3#include "FileManager.h"
4#include "HTTPSNetwork.h"
5
6#include "Exceptions/FileDoesNotExistException.h"
7
8using namespace std;
9
10namespace framework
11{
12 bool HTTPRequest::isWebFrameworkDynamicPages(const string& filePath)
13 {
14 size_t extension = filePath.find('.');
15
16 if (extension == string::npos)
17 {
18 return false;
19 }
20
21 return string_view(filePath.data() + extension) == webFrameworkDynamicPagesExtension;
22 }
23
24 web::HTTPParser HTTPRequest::sendRequestToAnotherServer(string_view ip, string_view port, string_view request, DWORD timeout, bool useHTTPS)
25 {
26 streams::IOSocketStream stream
27 (
28 useHTTPS ?
29 make_unique<web::HTTPSNetwork>(ip, port, timeout) :
30 make_unique<web::HTTPNetwork>(ip, port, timeout)
31 );
32 string response;
33
34 stream << request;
35 stream >> response;
36
37 return web::HTTPParser(response);
38 }
39
40 HTTPRequest::HTTPRequest(SessionsManager& session, const web::BaseTCPServer& serverReference, interfaces::IStaticFile& staticResources, interfaces::IDynamicFile& dynamicResources, sqlite::SQLiteManager& database, sockaddr clientAddr, streams::IOSocketStream& stream) :
41 session(session),
42 serverReference(serverReference),
43 stream(stream),
44 database(database),
45 clientAddr(clientAddr),
46 staticResources(staticResources),
47 dynamicResources(dynamicResources)
48 {
49
50 }
51
52 const string& HTTPRequest::getRawParameters() const
53 {
54 return parser.getParameters();
55 }
56
57 const string& HTTPRequest::getMethod() const
58 {
59 return parser.getMethod();
60 }
61
62 const unordered_map<string, string>& HTTPRequest::getKeyValueParameters() const
63 {
64 return parser.getKeyValueParameters();
65 }
66
67 string HTTPRequest::getHTTPVersion() const
68 {
69 return "HTTP/" + to_string(parser.getHTTPVersion());
70 }
71
72 const web::HeadersMap& HTTPRequest::getHeaders() const
73 {
74 return parser.getHeaders();
75 }
76
77 const string& HTTPRequest::getBody() const
78 {
79 return parser.getBody();
80 }
81
82 void HTTPRequest::setAttribute(const string& name, const string& value)
83 {
84 session.setAttribute(this->getClientIpV4(), name, value);
85 }
86
87 string HTTPRequest::getAttribute(const string& name)
88 {
89 return session.getAttribute(this->getClientIpV4(), name);
90 }
91
92 void HTTPRequest::deleteSession()
93 {
94 session.deleteSession(this->getClientIpV4());
95 }
96
97 void HTTPRequest::deleteAttribute(const string& name)
98 {
99 session.deleteAttribute(this->getClientIpV4(), name);
100 }
101
102 web::HeadersMap HTTPRequest::getCookies() const
103 {
104 web::HeadersMap result;
105 const web::HeadersMap& headers = parser.getHeaders();
106
107 if (auto it = headers.find("Cookie"); it != headers.end())
108 {
109 const string& cookies = it->second;
110 size_t offset = 0;
111
112 while (true)
113 {
114 size_t findKey = cookies.find('=', offset);
115 size_t findValue = cookies.find("; ", offset);
116 string::const_iterator startKey = cookies.begin() + offset;
117 string::const_iterator endKey = cookies.begin() + findKey;
118 string::const_iterator startValue = endKey + 1;
119 string::const_iterator endValue = findValue != string::npos ? (cookies.begin() + findValue) : (cookies.end());
120
121 result.try_emplace(string(startKey, endKey), string(startValue, endValue));
122
123 if (findValue == string::npos)
124 {
125 break;
126 }
127
128 offset = findValue + 2;
129 }
130 }
131
132 return result;
133 }
134
135 void HTTPRequest::sendAssetFile(const string& filePath, HTTPResponse& response, const unordered_map<string, string>& variables, bool isBinary, const string& fileName)
136 {
137 HTTPRequest::isWebFrameworkDynamicPages(filePath) ?
138 this->sendDynamicFile(filePath, response, variables, isBinary, fileName) :
139 this->sendStaticFile(filePath, response, isBinary, fileName);
140 }
141
142 void HTTPRequest::sendStaticFile(const string& filePath, HTTPResponse& response, bool isBinary, const string& fileName)
143 {
144 staticResources.sendStaticFile(filePath, response, isBinary, fileName);
145 }
146
147 void HTTPRequest::sendDynamicFile(const string& filePath, HTTPResponse& response, const unordered_map<string, string>& variables, bool isBinary, const string& fileName)
148 {
149 dynamicResources.sendDynamicFile(filePath, response, variables, isBinary, fileName);
150 }
151
152 void HTTPRequest::streamFile(string_view filePath, HTTPResponse& response, string_view fileName, size_t chunkSize)
153 {
154 filesystem::path assetFilePath(staticResources.getPathToAssets() / filePath);
155 file_manager::Cache& cache = file_manager::FileManager::getInstance().getCache();
156
157 if (!filesystem::exists(assetFilePath))
158 {
159 throw file_manager::exceptions::FileDoesNotExistException(assetFilePath);
160 }
161
162 web::HTTPBuilder builder = web::HTTPBuilder().
163 headers
164 (
165 "Date", HTTPResponse::getFullDate(),
166 "Server", "WebFramework-Server",
167 "Content-Type", "application/octet-stream",
168 "Content-Disposition", format(R"(attachment; filename="{}")", fileName),
169 "Connection", "keep-alive",
170 "Content-Length", filesystem::file_size(assetFilePath)
171 ).
172 responseCode(web::responseCodes::ok);
173
174 response.setIsValid(false);
175
176#pragma warning(push)
177#pragma warning(disable: 26800)
178 if (cache.contains(assetFilePath))
179 {
180 const string& data = cache[assetFilePath];
181
182 builder.headers
183 (
184 "DownloadType", "from-cache"
185 );
186
187 stream << builder.build(data);
188
189 return;
190 }
191
192 ifstream fileStream(assetFilePath, ios_base::binary);
193 string chunk(chunkSize, '\0');
194
195 streamsize dataSize = fileStream.read(chunk.data(), chunkSize).gcount();
196
197 if (dataSize != chunkSize)
198 {
199 chunk.resize(dataSize);
200 }
201
202 cache.appendCache(assetFilePath, chunk);
203
204 builder.headers
205 (
206 "DownloadType", "from-file"
207 );
208
209 stream << builder.build() + chunk;
210#pragma warning(pop)
211
212 while (!fileStream.eof())
213 {
214 dataSize = fileStream.read(chunk.data(), chunkSize).gcount();
215
216 if (dataSize != chunkSize)
217 {
218 chunk.resize(dataSize);
219 }
220
221 cache.appendCache(assetFilePath, chunk);
222
223 stream << chunk;
224 }
225 }
226
227 void HTTPRequest::registerDynamicFunction(const string& functionName, function<string(const vector<string>&)>&& function)
228 {
229 dynamicResources.registerDynamicFunction(functionName, move(function));
230 }
231
232 void HTTPRequest::unregisterDynamicFunction(const string& functionName)
233 {
234 dynamicResources.unregisterDynamicFunction(functionName);
235 }
236
237 bool HTTPRequest::isDynamicFunctionRegistered(const string& functionName)
238 {
239 return dynamicResources.isDynamicFunctionRegistered(functionName);
240 }
241
242 const json::JSONParser& HTTPRequest::getJSON() const
243 {
244 return parser.getJSON();
245 }
246
247 const vector<string>& HTTPRequest::getChunks() const
248 {
249 return parser.getChunks();
250 }
251
252 const web::HTTPParser& HTTPRequest::getParser() const
253 {
254 return parser;
255 }
256
257 string HTTPRequest::getClientIpV4() const
258 {
259 return web::BaseTCPServer::getClientIpV4(clientAddr);
260 }
261
262 string HTTPRequest::getServerIpV4() const
263 {
264 return serverReference.getServerIpV4();
265 }
266
267 uint16_t HTTPRequest::getClientPort() const
268 {
269 return web::BaseTCPServer::getClientPortV4(clientAddr);
270 }
271
272 uint16_t HTTPRequest::getServerPort() const
273 {
274 return serverReference.getServerPortV4();
275 }
276
277 template<>
278 WEB_FRAMEWORK_API const string& HTTPRequest::getRouteParameter<string>(const string& routeParameterName)
279 {
280 return get<string>(routeParameters.at(routeParameterName));
281 }
282
283 template<>
284 WEB_FRAMEWORK_API const int64_t& HTTPRequest::getRouteParameter<int64_t>(const string& routeParameterName)
285 {
286 return get<int64_t>(routeParameters.at(routeParameterName));
287 }
288
289 template<>
290 WEB_FRAMEWORK_API const double& HTTPRequest::getRouteParameter<double>(const string& routeParameterName)
291 {
292 return get<double>(routeParameters.at(routeParameterName));
293 }
294
295 streams::IOSocketStream& operator >> (streams::IOSocketStream& stream, HTTPRequest& request)
296 {
297 string data;
298
299 stream >> data;
300
301 if (stream.eof() || stream.bad())
302 {
303 return stream;
304 }
305
306 request.parser.parse(data);
307
308 return stream;
309 }
310
311 ostream& operator << (ostream& stream, const HTTPRequest& request)
312 {
313 const web::HTTPParser& parser = request.parser;
314 const auto& headers = parser.getHeaders();
315
316 stream << parser.getMethod() << " " << parser.getParameters() << " " << parser.getHTTPVersion() << endl;
317
318 for (const auto& [name, value] : headers)
319 {
320 stream << name << ": " << value << endl;
321 }
322
323 stream << endl << parser.getBody();
324
325 return stream;
326 }
327}
Parsing HTTP request.
Definition HTTPRequest.h:25
HTTPBuilder wrapper.