diff -r c7b73000a1ed -r 4d8a55a7618b src/server/proxy/httpclient.c --- a/src/server/proxy/httpclient.c Sat Feb 21 11:17:37 2026 +0100 +++ b/src/server/proxy/httpclient.c Sat Feb 21 13:12:39 2026 +0100 @@ -207,7 +207,7 @@ log_ereport(LOG_FAILURE, "http-client-start: connect failed: %s", strerror(err)); } } else { - // TODO: call client_connected directly + ret = 0; // TODO } if(ret) { @@ -261,21 +261,26 @@ static int client_io(EventHandler *ev, Event *event) { HttpClient *client = event->cookie; - if(client->transfer_buffer_pos < client->transfer_buffer_len) { - if(client_send_request(client)) { - return client->error == 0; + if(client->stage == 0) { + if(client->transfer_buffer_pos < client->transfer_buffer_len) { + if(client_send_request(client)) { + return client->error == 0; + } } - } - - // do we need to send a request body? - if(client->req_content_length != 0) { - if(client_send_request_body(client)) { - return client->error == 0; + + // do we need to send a request body? + if(client->req_content_length != 0) { + if(client_send_request_body(client)) { + return client->error == 0; + } } } // writing complete, switch to read events event->events = EVENT_POLLIN; + client->stage = 1; + client->transfer_buffer_pos = 0; + client->transfer_buffer_len = 0; if(client_read_response_header(client)) { return client->error == 0; @@ -404,6 +409,8 @@ return 0; } +// returns 0 success +// 1 would block or error static int client_read_response_header(HttpClient *client) { if(client->response_header_complete) { return 0; @@ -432,7 +439,12 @@ int ret = client->response_start(client, client->statuscode, msg.ptr, client->response_start_userdata); msg.ptr[msg.length] = t; - // TODO: check ret + if(ret != 0) { + if(ret != HTTP_CLIENT_CALLBACK_WOULD_BLOCK) { + client->error = 1; + } + return 1; + } } break; } @@ -508,19 +520,55 @@ return 0; } +// uses the response_body_write callback to write the content of the +// transfer buffer +// returns 0 success +// 1 would block or error +static int client_write_response(HttpClient *client) { + while(client->transfer_buffer_pos < client->transfer_buffer_len) { + char *buf = client->transfer_buffer + client->transfer_buffer_pos; + size_t len = client->transfer_buffer_len - client->transfer_buffer_pos; + int ret = client->response_body_write(client, buf, len, client->response_body_write_userdata); + if(ret > 0) { + client->transfer_buffer_pos += ret; + } else if(ret == 0) { + // EOF? + // check if the write is incomplete, which would be an error + client->error == client->transfer_buffer_pos < client->transfer_buffer_len; + return client->error; + } else { + if(ret != HTTP_CLIENT_CALLBACK_WOULD_BLOCK) { + client->error = 1; + } + return 1; + } + } + return 0; +} + +// returns 0 success +// 1 would block or error static int client_read_response_body(HttpClient *client) { if(!client->stream) { return 0; // no input stream -> no response body } + // does the transfer buffer still contains bytes, that should be written? + if(client_write_response(client)) { + return 1; + } + char *buf = client->transfer_buffer; size_t nbytes = client->transfer_buffer_alloc; ssize_t r; while((r = net_read(&client->stream->st, buf, nbytes)) > 0) { + client->transfer_buffer_len = r; + client->transfer_buffer_pos = 0; if(client->response_body_write) { - int ret = client->response_body_write(client, buf, r, client->response_body_write_userdata); - // TODO: check ret + if(client_write_response(client)) { + return 1; + } } } @@ -765,6 +813,8 @@ EventHandler dummy; HttpClient *client = http_client_new(&dummy); create_req_buffer(client); + client->transfer_buffer_pos = 0; + client->transfer_buffer_len = 0; client->req_content_length = -1; int fds[2];