-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRequest.cpp
More file actions
206 lines (164 loc) · 5.8 KB
/
Copy pathRequest.cpp
File metadata and controls
206 lines (164 loc) · 5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
#include "Request.hpp"
#include "Utils.hpp"
#include <sstream>
#include <iostream>
Request::Request(const std::string buffer)
: rawRequest(buffer),
uri(""),
method(""),
body(""),
host(""),
ContentLength(0),
isMultiPart(false),
keepAlive(false),
RequestIsValid(false) {
debug("[Request]: Created new request");
}
Request::~Request() {
debug("[Request]: Destroying request");
}
int Request::preProcessRequest() {
debug("[Request]: Pre-processing request");
// Extract method, URI, and HTTP version
std::istringstream request_stream(rawRequest);
std::string request_line;
if (!std::getline(request_stream, request_line) || request_line.empty()) {
debug("[Request]: Invalid or empty request line");
return -1;
}
// Remove trailing \r if present
if (!request_line.empty() && request_line[request_line.length() - 1] == '\r') {
request_line.erase(request_line.length() - 1);
}
std::istringstream request_line_stream(request_line);
std::string tempMethod, tempUri, version;
request_line_stream >> tempMethod >> tempUri >> version;
if (tempMethod.empty() || tempUri.empty() || version.empty()) {
debug("[Request]: Incomplete request line");
return -1;
}
// Store method and URI in the private fields
const_cast<std::string&>(method) = tempMethod;
const_cast<std::string&>(uri) = tempUri;
debug("[Request]: Method: " + method + ", URI: " + uri + ", Version: " + version);
// Parse headers
std::string header_block;
std::string line;
while (std::getline(request_stream, line) && !line.empty() && line != "\r") {
header_block += line + "\n";
// Specifically look for Host header (optimization)
if (line.find("Host:") == 0 || line.find("host:") == 0) {
std::string hostValue = line.substr(line.find(":") + 1);
// Remove whitespace at beginning and end
hostValue.erase(0, hostValue.find_first_not_of(" \t"));
hostValue.erase(hostValue.find_last_not_of(" \t\r\n") + 1);
const_cast<std::string&>(host) = hostValue;
debug("[Request]: Found Host header: " + host);
}
}
if (!headers.parseHeaderLines(header_block)) {
debug("[Request]: Failed to parse headers");
return -1;
}
// Extract host from headers
const_cast<std::string&>(host) = headers.get("Host");
// Check for multipart content
std::string contentType = headers.get("Content-Type");
isMultiPart = (contentType.find("multipart/form-data") != std::string::npos);
// Extract boundary if multipart
if (isMultiPart) {
size_t boundaryPos = contentType.find("boundary=");
if (boundaryPos != std::string::npos) {
boundary = contentType.substr(boundaryPos + 9);
// Remove any trailing whitespace or quotes
boundary.erase(boundary.find_last_not_of(" \n\r\t\"") + 1);
// Remove any leading whitespace or quotes
boundary.erase(0, boundary.find_first_not_of(" \n\r\t\""));
}
}
// Check for Content-Length
std::string contentLengthStr = headers.get("Content-Length");
if (!contentLengthStr.empty()) {
ContentLength = atoi(contentLengthStr.c_str());
} else {
ContentLength = 0;
}
// Check connection type
std::string connection = headers.get("Connection");
keepAlive = (connection.find("keep-alive") != std::string::npos);
// Extract body if present in this chunk
std::streampos headerEnd = request_stream.tellg();
if (headerEnd != std::streampos(std::streamoff(-1))) {
size_t bodyStart = static_cast<size_t>(headerEnd);
if (bodyStart < rawRequest.size()) {
const_cast<std::string&>(body) = rawRequest.substr(bodyStart);
}
}
return 0;
}
int Request::validateRequest() {
debug("[Request]: Validating request");
// Check if method is supported
if (method != "GET" && method != "POST" && method != "DELETE") {
debug("[Request]: Unsupported method: " + method);
return -1;
}
// Check if URI is valid
if (uri.empty() || uri[0] != '/') {
debug("[Request]: Invalid URI: " + uri);
return -1;
}
// If this is a POST request, check for Content-Type and Content-Length
if (method == "POST") {
if (!headers.has("Content-Type")) {
debug("[Request]: POST request missing Content-Type");
return -1;
}
if (!headers.has("Content-Length")) {
debug("[Request]: POST request missing Content-Length");
return -1;
}
}
// Check for host header in HTTP/1.1
if (rawRequest.find("HTTP/1.1") != std::string::npos && host.empty()) {
debug("[Request]: HTTP/1.1 request missing Host header");
return -1;
}
// More validation logic can be added here
RequestIsValid = true;
return 0;
}
HttpHeaders Request::getHeaders() {
return headers;
}
// Additional getters
const std::string& Request::getUri() const {
return uri;
}
const std::string& Request::getMethod() const {
return method;
}
const std::string& Request::getBody() const {
return body;
}
const std::string& Request::getHost() const {
return host;
}
// const std::string& Request::getRawRequestData() const {
// return rawRequest;
// }
int Request::getContentLength() const {
return ContentLength;
}
bool Request::isMultiPartRequest() const {
return isMultiPart;
}
const std::string& Request::getBoundary() const {
return boundary;
}
bool Request::isKeepAliveRequest() const {
return keepAlive;
}
bool Request::isValid() const {
return RequestIsValid;
}