From 8cf72032cf4eb256b84996977e56ecf9859ca427 Mon Sep 17 00:00:00 2001 From: liulanzheng Date: Tue, 17 Dec 2024 16:13:53 +0800 Subject: [PATCH] add set body buffer for http client Signed-off-by: liulanzheng --- net/http/client.cpp | 9 ++++++++- net/http/client.h | 22 +++++++++++++++++++--- net/http/message.h | 4 ++-- net/http/test/client_function_test.cpp | 12 ++++++++++++ 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/net/http/client.cpp b/net/http/client.cpp index 5847175e..20b7add8 100644 --- a/net/http/client.cpp +++ b/net/http/client.cpp @@ -222,7 +222,14 @@ class ClientImpl : public Client { LOG_ERROR_RETURN(0, ROUNDTRIP_NEED_RETRY, "send header failed, retry"); } sock->timeout(tmo.timeout()); - if (op->body_stream) { + if (op->body_buffer_size > 0) { + // send body_buffer + if (req.write(op->body_buffer, op->body_buffer_size) < 0) { + sock->close(); + req.reset_status(); + LOG_ERROR_RETURN(0, ROUNDTRIP_NEED_RETRY, "send body buffer failed, retry"); + } + } else if (op->body_stream) { // send body_stream if (req.write_stream(op->body_stream) < 0) { sock->close(); diff --git a/net/http/client.h b/net/http/client.h index 34d5f0ad..9cad6df1 100644 --- a/net/http/client.h +++ b/net/http/client.h @@ -62,9 +62,10 @@ class Client : public Object { bool enable_proxy = false; std::string_view uds_path; // If set, Unix Domain Socket will be used instead of TCP. // URL should still be the format of http://localhost/xxx - IStream* body_stream = nullptr; // use body_stream as body - using BodyWriter = Delegate; // or call body_writer if body_stream - BodyWriter body_writer = {}; // is not set + + IStream* body_stream = nullptr; // priority: set_body > body_stream > body_writer + using BodyWriter = Delegate; + BodyWriter body_writer = {}; static Operation* create(Client* c, Verb v, std::string_view url, uint16_t buf_size = 64 * 1024 - 1) { @@ -91,9 +92,22 @@ class Client : public Object { uds_path = unix_socket_path; return _client->call(this); } + // set body buffer and set content length automatically + void set_body(const void *buf, size_t size) { + body_buffer = buf; + body_buffer_size = size; + req.headers.content_length(size); + } + void set_body(std::string_view buf) { + set_body(buf.data(), buf.length()); + } + protected: Client* _client; + const void *body_buffer = nullptr; + size_t body_buffer_size = 0; + char _buf[0]; Operation(Client* c, Verb v, std::string_view url, uint16_t buf_size) : req(_buf, buf_size, v, url, c->has_proxy()), @@ -106,6 +120,8 @@ class Client : public Object { explicit Operation(uint16_t buf_size) : req(_buf, buf_size), _client(nullptr) {} Operation() = delete; ~Operation() = default; + + friend class ClientImpl; }; template diff --git a/net/http/message.h b/net/http/message.h index 9b85b9b3..b95f6422 100644 --- a/net/http/message.h +++ b/net/http/message.h @@ -98,9 +98,9 @@ class Message : public IStream { ssize_t write_stream(IStream *stream, size_t size_limit = -1); int close() override { return 0; } - // size of body + // size of body: infer from Content-Range/Content-Length in response header size_t body_size() const; - // size of origin resource + // size of origin resource: infer from Content-Range/Content-Length in response header ssize_t resource_size() const; // in general, it is called automatically diff --git a/net/http/test/client_function_test.cpp b/net/http/test/client_function_test.cpp index 5fa4f2b8..efbe8f77 100644 --- a/net/http/test/client_function_test.cpp +++ b/net/http/test/client_function_test.cpp @@ -213,6 +213,18 @@ TEST(http_client, post) { ret = op2->resp.read(buf, 4096); EXPECT_EQ(ret, 7); EXPECT_EQ(0, strncmp(buf, "success", ret)); + + // body buffer test + auto op3 = client->new_operation(Verb::POST, target); + DEFER(client->destroy_operation(op3)); + void *body_buf = malloc(st.st_size); + EXPECT_EQ(st.st_size, file->pread(body_buf, st.st_size, 0)); + op3->set_body(body_buf, st.st_size); + client->call(op3); + EXPECT_EQ(200, op3->resp.status_code()); + ret = op3->resp.read(buf, 4096); + EXPECT_EQ(ret, 7); + EXPECT_EQ(0, strncmp(buf, "success", ret)); }