Add http post feature for HttpClient (#773)
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,3 +8,5 @@ gensrc/build
|
||||
fe/target
|
||||
thirdparty/src
|
||||
*.so.tmp
|
||||
.DS_Store
|
||||
*.iml
|
||||
|
||||
@ -27,6 +27,10 @@ HttpClient::~HttpClient() {
|
||||
curl_easy_cleanup(_curl);
|
||||
_curl = nullptr;
|
||||
}
|
||||
if(_header_list != nullptr) {
|
||||
curl_slist_free_all(_header_list);
|
||||
_header_list = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Status HttpClient::init(const std::string& url) {
|
||||
@ -39,6 +43,10 @@ Status HttpClient::init(const std::string& url) {
|
||||
curl_easy_reset(_curl);
|
||||
}
|
||||
|
||||
if(_header_list != nullptr) {
|
||||
curl_slist_free_all(_header_list);
|
||||
_header_list = nullptr;
|
||||
}
|
||||
// set error_buf
|
||||
_error_buf[0] = 0;
|
||||
auto code = curl_easy_setopt(_curl, CURLOPT_ERRORBUFFER, _error_buf);
|
||||
@ -131,6 +139,18 @@ size_t HttpClient::on_response_data(const void* data, size_t length) {
|
||||
return length;
|
||||
}
|
||||
|
||||
// Status HttpClient::execute_post_request(const std::string& post_data, const std::function<bool(const void* data, size_t length)>& callback = {}) {
|
||||
// _callback = &callback;
|
||||
// set_post_body(post_data);
|
||||
// return execute(callback);
|
||||
// }
|
||||
|
||||
Status HttpClient::execute_post_request(const std::string& post_data, std::string* response) {
|
||||
set_method(POST);
|
||||
set_post_body(post_data);
|
||||
return execute(response);
|
||||
}
|
||||
|
||||
Status HttpClient::execute(const std::function<bool(const void* data, size_t length)>& callback) {
|
||||
_callback = &callback;
|
||||
auto code = curl_easy_perform(_curl);
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
#include "http/http_headers.h"
|
||||
#include "http/http_method.h"
|
||||
#include "http/utils.h"
|
||||
|
||||
#include "http/http_response.h"
|
||||
namespace doris {
|
||||
|
||||
// Helper class to access HTTP resource
|
||||
@ -54,6 +54,19 @@ public:
|
||||
curl_easy_setopt(_curl, CURLOPT_PASSWORD, passwd.c_str());
|
||||
}
|
||||
|
||||
// content_type such as "application/json"
|
||||
void set_content_type(const std::string content_type) {
|
||||
std::string scratch_str = "Content-Type: " + content_type;
|
||||
_header_list = curl_slist_append(_header_list, scratch_str.c_str());
|
||||
curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _header_list);
|
||||
}
|
||||
|
||||
// you must set CURLOPT_POSTFIELDSIZE before CURLOPT_COPYPOSTFIELDS options, otherwise will cause request hanging up
|
||||
void set_post_body(const std::string& post_body) {
|
||||
curl_easy_setopt(_curl, CURLOPT_POSTFIELDSIZE, (long)post_body.length());
|
||||
curl_easy_setopt(_curl, CURLOPT_COPYPOSTFIELDS, post_body.c_str());
|
||||
}
|
||||
|
||||
// TODO(zc): support set header
|
||||
// void set_header(const std::string& key, const std::string& value) {
|
||||
// _cntl.http_request().SetHeader(key, value);
|
||||
@ -85,6 +98,12 @@ public:
|
||||
return cl;
|
||||
}
|
||||
|
||||
long get_http_status() const {
|
||||
long code;
|
||||
curl_easy_getinfo(_curl, CURLINFO_RESPONSE_CODE, &code);
|
||||
return code;
|
||||
}
|
||||
|
||||
// execute a head method
|
||||
Status head() {
|
||||
set_method(HEAD);
|
||||
@ -95,6 +114,8 @@ public:
|
||||
// a file to local_path
|
||||
Status download(const std::string& local_path);
|
||||
|
||||
Status execute_post_request(const std::string& post_data, std::string* response);
|
||||
|
||||
// execute a simple method, and its response is saved in response argument
|
||||
Status execute(std::string* response);
|
||||
|
||||
@ -111,6 +132,7 @@ private:
|
||||
using HttpCallback = std::function<bool(const void* data, size_t length)>;
|
||||
const HttpCallback* _callback = nullptr;
|
||||
char _error_buf[CURL_ERROR_SIZE];
|
||||
curl_slist *_header_list = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -47,7 +47,28 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class HttpClientTestSimplePostHandler : public HttpHandler {
|
||||
public:
|
||||
void handle(HttpRequest* req) override {
|
||||
std::string user;
|
||||
std::string passwd;
|
||||
if (!parse_basic_auth(*req, &user, &passwd) || user != "test1") {
|
||||
HttpChannel::send_basic_challenge(req, "abc");
|
||||
return;
|
||||
}
|
||||
if (req->method() == HttpMethod::POST) {
|
||||
std::string post_body = req->get_request_body();
|
||||
if (!post_body.empty()) {
|
||||
HttpChannel::send_reply(req, post_body);
|
||||
} else {
|
||||
HttpChannel::send_reply(req, "empty");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static HttpClientTestSimpleGetHandler s_simple_get_handler = HttpClientTestSimpleGetHandler();
|
||||
static HttpClientTestSimplePostHandler s_simple_post_handler = HttpClientTestSimplePostHandler();
|
||||
static EvHttpServer* s_server = nullptr;
|
||||
|
||||
class HttpClientTest : public testing::Test {
|
||||
@ -59,6 +80,7 @@ public:
|
||||
s_server = new EvHttpServer(29386);
|
||||
s_server->register_handler(GET, "/simple_get", &s_simple_get_handler);
|
||||
s_server->register_handler(HEAD, "/simple_get", &s_simple_get_handler);
|
||||
s_server->register_handler(POST, "/simple_post", &s_simple_post_handler);
|
||||
s_server->start();
|
||||
}
|
||||
|
||||
@ -109,9 +131,24 @@ TEST_F(HttpClientTest, get_failed) {
|
||||
auto st = client.init("http://127.0.0.1:29386/simple_get");
|
||||
ASSERT_TRUE(st.ok());
|
||||
client.set_method(GET);
|
||||
client.set_basic_auth("test1", "");
|
||||
std::string response;
|
||||
st = client.execute(&response);
|
||||
ASSERT_FALSE(st.ok());
|
||||
ASSERT_FALSE(!st.ok());
|
||||
}
|
||||
|
||||
TEST_F(HttpClientTest, post_normal) {
|
||||
HttpClient client;
|
||||
auto st = client.init("http://127.0.0.1:29386/simple_post");
|
||||
ASSERT_TRUE(st.ok());
|
||||
client.set_method(POST);
|
||||
client.set_basic_auth("test1", "");
|
||||
std::string response;
|
||||
std::string request_body = "simple post body query";
|
||||
st = client.execute_post_request(request_body, &response);
|
||||
ASSERT_TRUE(st.ok());
|
||||
ASSERT_EQ(response.length(), request_body.length());
|
||||
ASSERT_STREQ(response.c_str(), request_body.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user