Add tests for proxy & better error checking

This commit is contained in:
ozanarmagan 2023-06-15 13:52:59 +03:00
parent 67cb5349c9
commit ec48c5a0ff
4 changed files with 164 additions and 4 deletions

View File

@ -2155,11 +2155,33 @@ bool post_proxy(const std::shared_ptr<http_req>& req, const std::shared_ptr<http
std::string body, url, method;
std::unordered_map<std::string, std::string> headers;
try {
body = req_json["body"].get<std::string>();
if(req_json.count("url") == 0 || req_json.count("method") == 0) {
res->set_400("Missing required fields.");
return false;
}
if(!req_json["url"].is_string() || !req_json["method"].is_string() || req_json["url"].get<std::string>().empty() || req_json["method"].get<std::string>().empty()) {
res->set_400("URL and method must be non-empty strings.");
return false;
}
try {
if(req_json.count("body") != 0 && !req_json["body"].is_string()) {
res->set_400("Body must be a string.");
return false;
}
if(req_json.count("headers") != 0 && !req_json["headers"].is_object()) {
res->set_400("Headers must be a JSON object.");
return false;
}
if(req_json.count("body")) {
body = req_json["body"].get<std::string>();
}
url = req_json["url"].get<std::string>();
method = req_json["method"].get<std::string>();
headers = req_json["headers"].get<std::unordered_map<std::string, std::string>>();
if(req_json.count("headers")) {
headers = req_json["headers"].get<std::unordered_map<std::string, std::string>>();
}
} catch(const std::exception& e) {
LOG(ERROR) << "JSON error: " << e.what();
res->set_400("Bad JSON.");

View File

@ -34,7 +34,9 @@ http_proxy_res_t HttpProxy::send(const std::string& url, const std::string& meth
res.status_code = client.delete_response(url, res.body, res.headers);
} else {
res.status_code = 400;
res.body = "Invalid method: " + method;
nlohmann::json j;
j["message"] = "Parameter `method` must be one of GET, POST, PUT, DELETE.";
res.body = j.dump();
}
// add to cache

View File

@ -13,6 +13,15 @@ Option<bool> RemoteEmbedder::validate_string_properties(const nlohmann::json& mo
long RemoteEmbedder::call_remote_api(const std::string& method, const std::string& url, const std::string& body, std::string& res_body,
std::map<std::string, std::string>& headers, const std::unordered_map<std::string, std::string>& req_headers) {
if(raft_server == nullptr) {
if(method == "GET") {
return HttpClient::get_instance().get_response(url, res_body, headers, req_headers, 10000, true);
} else if(method == "POST") {
return HttpClient::get_instance().post_response(url, body, res_body, headers, req_headers, 10000, true);
} else {
return 400;
}
}
auto leader_url = raft_server->get_leader_url();
leader_url += "proxy";
nlohmann::json req_body;

View File

@ -956,3 +956,130 @@ TEST_F(CoreAPIUtilsTest, ExportIncludeExcludeFieldsWithFilter) {
collectionManager.drop_collection("coll1");
}
TEST_F(CoreAPIUtilsTest, TestProxy) {
std::string res;
std::unordered_map<std::string, std::string> headers;
std::map<std::string, std::string> res_headers;
std::string url = "https://typesense.org";
long expected_status_code = HttpClient::get_instance().get_response(url, res, res_headers, headers);
auto req = std::make_shared<http_req>();
auto resp = std::make_shared<http_res>(nullptr);
nlohmann::json body;
body["url"] = url;
body["method"] = "GET";
body["headers"] = headers;
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(expected_status_code, resp->status_code);
ASSERT_EQ(res, resp->body);
}
TEST_F(CoreAPIUtilsTest, TestProxyInvalid) {
nlohmann::json body;
auto req = std::make_shared<http_req>();
auto resp = std::make_shared<http_res>(nullptr);
// test with url as empty string
body["url"] = "";
body["method"] = "GET";
body["headers"] = nlohmann::json::object();
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(400, resp->status_code);
ASSERT_EQ("URL and method must be non-empty strings.", nlohmann::json::parse(resp->body)["message"]);
// test with url as integer
body["url"] = 123;
body["method"] = "GET";
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(400, resp->status_code);
ASSERT_EQ("URL and method must be non-empty strings.", nlohmann::json::parse(resp->body)["message"]);
// test with no url parameter
body.erase("url");
body["method"] = "GET";
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(400, resp->status_code);
ASSERT_EQ("Missing required fields.", nlohmann::json::parse(resp->body)["message"]);
// test with invalid method
body["url"] = "https://typesense.org";
body["method"] = "INVALID";
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(400, resp->status_code);
ASSERT_EQ("Parameter `method` must be one of GET, POST, PUT, DELETE.", nlohmann::json::parse(resp->body)["message"]);
// test with method as integer
body["method"] = 123;
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(400, resp->status_code);
ASSERT_EQ("URL and method must be non-empty strings.", nlohmann::json::parse(resp->body)["message"]);
// test with no method parameter
body.erase("method");
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(400, resp->status_code);
ASSERT_EQ("Missing required fields.", nlohmann::json::parse(resp->body)["message"]);
// test with body as integer
body["method"] = "POST";
body["body"] = 123;
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(400, resp->status_code);
ASSERT_EQ("Body must be a string.", nlohmann::json::parse(resp->body)["message"]);
// test with headers as integer
body["body"] = "";
body["headers"] = 123;
req->body = body.dump();
post_proxy(req, resp);
ASSERT_EQ(400, resp->status_code);
ASSERT_EQ("Headers must be a JSON object.", nlohmann::json::parse(resp->body)["message"]);
}