Commit Diff


commit - c4c2cf10fce4581c26b40cbb57746f2beb9b0527
commit + d5ea6c0a1f11baf2b351bc54290c178c5eb0d057
blob - 6e5a7417185ee781c80bc0a32e61db0ffe0436f1
blob + 1ea22be8276cad320975103381f28a112c025b98
--- http/http.ha
+++ http/http.ha
@@ -67,9 +67,10 @@ type client = struct {
 	fp: io::file,
 	in: bufio::scanner,
 	first_line: bool,
+	request_done: bool,
 	request: request,
 	response: reswriter,
-	// routefn: (void | routefn),
+	routefn: routefn,
 	mux: *mux,
 };
 
@@ -110,13 +111,14 @@ fn acceptclt(f: io::file, ev: ev::event, data: nullabl
 	let clt = alloc(client {
 		fp = sock,
 		mux = mux,
-		// routefn = void,
 		in = bufio::newscanner(sock, types::SIZE_MAX),
 		first_line = true,
 		response = new_reswriter(sock),
+		routefn = &route_notfound,
 		...
 	});
 
+	log::printfln("adding client {} ({})", sock: int, clt: uintptr);
 	ev::add(sock, ev::READ, &handleclt, clt);
 };
 
@@ -188,7 +190,9 @@ fn delclient(c: *client) void = {
 fn handleclt(f: io::file, ev: ev::event, data: nullable *opaque) void = {
 	let clt = data: *client;
 
-	match (do_request(clt)) {
+	log::printfln("in handleclt for {} ({})", f: int, clt: uintptr);
+
+	match (respond(clt)) {
 	case let err: error =>
 		log::printfln("failure: {}", strerror(err));
 		delclient(clt);
@@ -196,13 +200,19 @@ fn handleclt(f: io::file, ev: ev::event, data: nullabl
 	case =>
 		// XXX wait if there is still data pending.
 		if (clt.response.done) {
+			log::printfln("done for {}", f: int);
 			delclient(clt);
 			return;
 		};
+
+		log::printfln("not done for {}, will retry later", f: int);
+		ev::add(clt.fp, ev::READ | ev::WRITE, &handleclt, clt);
 	};
 };
 
-fn do_request(clt: *client) (void | error) = {
+fn handle_request(clt: *client) (void | error) = {
+	log::printfln("in handle_request");
+
 	match (parse_req(clt)) {
 	case let done: bool =>
 		if (!done)
@@ -222,20 +232,29 @@ fn do_request(clt: *client) (void | error) = {
 	let path = clt.request.path;
 	log::printfln("< GET {}", path);
 
-	let found = false;
 	for (let i = 0z; i < len(clt.mux); i += 1) {
 		if (fnmatch::fnmatch(clt.mux[i].pattern, path)) {
-			found = true;
-			clt.mux[i].routefn(&clt.request, &clt.response)?;
+			clt.routefn = clt.mux[i].routefn;
 			break;
 		};
 	};
 
-	if (!found) {
-		route_notfound(&clt.request, &clt.response)?;
+	clt.request_done = true;
+};
+
+fn respond(clt: *client) (void | error) = {
+	if (!clt.request_done)
+		handle_request(clt)?;
+	if (!clt.request_done)
+		return;
+
+	log::printfln("in respond");
+
+	if (!clt.response.done) {
+		clt.response.done = true;
+		clt.routefn(&clt.request, &clt.response)?;
 	};
 
-	clt.response.done = true;
 	reswriter_flush(&clt.response)?;
 };