Skip to content

Commit 0dc791b

Browse files
author
Yieen
committed
working POST requset with Transfer-encoding: chunked
1 parent 579de69 commit 0dc791b

File tree

4 files changed

+35
-20
lines changed

4 files changed

+35
-20
lines changed

include/http/Http.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class Http : public AConnection {
3939

4040
std::string _log;
4141

42+
std::string cgiProgramPathname;
43+
std::string cgiFilePathname;
44+
std::string cgiChunkedBody;
45+
4246
public:
4347
Http(Address const& client, Address const& host);
4448
~Http();
@@ -62,8 +66,7 @@ class Http : public AConnection {
6266
void processAutoindex(std::string uri);
6367
void processRedirect(std::string uri);
6468
void processError(std::string code, std::string reason, bool close = false);
65-
void processCgi(std::string const& uri, File const& file,
66-
std::string const& cgiPathname);
69+
void processCgi(std::string contentLength = "");
6770

6871
void addIndexToPath(File& file, std::string& uri);
6972
void checkResourceValidity(const File& file, const std::string& uri);

include/poll/AConnection.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class AConnection : public IFileDescriptor {
5353
void send(std::istream *msg);
5454
void cgiSend(std::string const &msg);
5555
void cgiCloseSendPipe();
56-
void runCGI(std::string const &program, std::vector<std::string> const &arg,
56+
void runCGI(std::string program, std::vector<std::string> const &arg,
5757
std::vector<std::string> const &env);
5858
void stopReceiving();
5959

src/http/Http.cpp

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -187,10 +187,17 @@ void Http::processFile(std::string uri) {
187187
checkResourceValidity(file, uri);
188188
if (_response.isReady()) return;
189189

190-
std::string cgiPath = getCgiPath(file.getExtension());
191-
if (cgiPath.size() > 0)
192-
return processCgi(uri, file, cgiPath);
193-
else if (_request.getMethod() == "POST") {
190+
cgiProgramPathname = getCgiPath(file.getExtension());
191+
if (cgiProgramPathname.size() > 0) {
192+
cgiFilePathname = file.getPath();
193+
if (_request.getMethod() == "POST" &&
194+
_request.getHeader("Transfer-Encoding") == "chunked") {
195+
cgiChunkedBody.clear();
196+
setReadState(CHUNK_SIZE);
197+
return;
198+
}
199+
return processCgi();
200+
} else if (_request.getMethod() == "POST") {
194201
processError("405", "Method Not Allowed", true);
195202
std::vector<std::string> allowed = getAllowedMethods();
196203
allowed.erase(std::find(allowed.begin(), allowed.end(), "POST"));
@@ -214,10 +221,8 @@ void Http::processFile(std::string uri) {
214221
_response.setReady();
215222
}
216223

217-
void Http::processCgi(std::string const &uri, File const &file,
218-
std::string const &cgiPathname) {
219-
(void)uri;
220-
std::string pathname = file.getPath();
224+
void Http::processCgi(std::string contentLength) {
225+
std::string pathname(cgiFilePathname);
221226
if (!startsWith(pathname, "/")) pathname.insert(0, cwd_g);
222227

223228
std::vector<std::string> env;
@@ -244,9 +249,10 @@ void Http::processCgi(std::string const &uri, File const &file,
244249
// Required amongst others to comply with CGI/1.1
245250
env.push_back("SCRIPT_NAME=" + pathname);
246251
if (_request.getMethod() == "POST") {
247-
env.push_back("CONTENT_LENGTH=" +
248-
_request.getHeader(
249-
"Content-length")); // TODO: What if request is chunked?
252+
if (contentLength.empty())
253+
env.push_back("CONTENT_LENGTH=" + _request.getHeader("Content-length"));
254+
else
255+
env.push_back("CONTENT_LENGTH=" + contentLength);
250256
if (_request.getHeader("Content-type") != "")
251257
env.push_back("CONTENT_TYPE=" + _request.getHeader("Content-type"));
252258
}
@@ -269,7 +275,7 @@ void Http::processCgi(std::string const &uri, File const &file,
269275
// env.push_back("PATH_INFO=" ...); // TODO: Implement
270276
// env.push_back("PATH_TRANSLATED=" ...);
271277

272-
runCGI(cgiPathname, std::vector<std::string>(1, pathname), env);
278+
runCGI(cgiProgramPathname, std::vector<std::string>(1, pathname), env);
273279
if (_request.getMethod() != "POST") cgiCloseSendPipe();
274280
_response.clear();
275281
}
@@ -329,13 +335,17 @@ void Http::processPutData(const std::string &data) {
329335
}
330336

331337
void Http::processPostData(std::string &data) {
332-
cgiSend(data);
333338
_currBodySize += data.size();
334339
if (_request.getHeader("Transfer-Encoding") == "chunked") {
335-
if (data.size() == 0) return cgiCloseSendPipe();
340+
if (data.size() == 0) {
341+
processCgi(toString(_currBodySize));
342+
cgiSend(cgiChunkedBody);
343+
return cgiCloseSendPipe();
344+
}
345+
cgiChunkedBody.append(data);
336346
return setReadState(CHUNK_SIZE);
337347
}
338-
348+
cgiSend(data);
339349
if (_currBodySize >= _expectedBodySize) {
340350
cgiCloseSendPipe();
341351
return;

src/poll/AConnection.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,9 +378,11 @@ void AConnection::onNoPollEvent(struct pollfd &) {
378378
}
379379

380380
/**
381-
* CGI
381+
* The http object is destroyed after calling fork(). The parameters must still
382+
* remain valid. program cannot be a reference to Http::cgiProgramPathname
383+
* because this is a member variable of the Http object, which is destroyed.
382384
*/
383-
void AConnection::runCGI(std::string const &program,
385+
void AConnection::runCGI(std::string program,
384386
std::vector<std::string> const &arg,
385387
std::vector<std::string> const &env) {
386388
int pipeInArray[2];

0 commit comments

Comments
 (0)