Return td_api::error for incorrect requests in JSON interface.

GitOrigin-RevId: 1c3e3f6c2b7a9828930bdfc185f332f6190467d1
This commit is contained in:
levlam 2019-08-06 03:29:16 +03:00
parent 8ae3ac91a4
commit a5a7e30ec5
6 changed files with 73 additions and 39 deletions

View File

@ -18,11 +18,29 @@ int main() {
void *client = td_json_client_create(); void *client = td_json_client_create();
// somehow share the client with other threads, which will be able to send requests via td_json_client_send // somehow share the client with other threads, which will be able to send requests via td_json_client_send
const bool test_incorrect_queries = true;
if (test_incorrect_queries) {
td_json_client_execute(nullptr, "{\"@type\":\"setLogVerbosityLevel\", \"new_verbosity_level\":3}");
td_json_client_execute(nullptr, "");
td_json_client_execute(nullptr, "test");
td_json_client_execute(nullptr, "\"test\"");
td_json_client_execute(nullptr, "{\"@type\":\"test\", \"@extra\":1}");
td_json_client_send(client, "{\"@type\":\"getFileMimeType\"}");
td_json_client_send(client, "{\"@type\":\"getFileMimeType\", \"@extra\":1}");
td_json_client_send(client, "{\"@type\":\"getFileMimeType\", \"@extra\":null}");
td_json_client_send(client, "{\"@type\":\"test\"}");
td_json_client_send(client, "[]");
td_json_client_send(client, "{\"@type\":\"test\", \"@extra\":1}");
td_json_client_send(client, "{\"@type\":\"sendMessage\", \"chat_id\":true, \"@extra\":1}");
td_json_client_send(client, "test");
}
const double WAIT_TIMEOUT = 10.0; // seconds const double WAIT_TIMEOUT = 10.0; // seconds
while (true) { while (true) {
const char *result = td_json_client_receive(client, WAIT_TIMEOUT); const char *result = td_json_client_receive(client, WAIT_TIMEOUT);
if (result != nullptr) { if (result != nullptr) {
// parse the result as JSON object and process it as an incoming update or an answer to a previously sent request // parse the result as a JSON object and process it as an incoming update or an answer to a previously sent request
// if (result is UpdateAuthorizationState with authorizationStateClosed) { // if (result is UpdateAuthorizationState with authorizationStateClosed) {
// break; // break;

View File

@ -4010,5 +4010,5 @@ testProxy server:string port:int32 type:ProxyType = Ok;
testGetDifference = Ok; testGetDifference = Ok;
//@description Does nothing and ensures that the Update object is used; for testing only. This is an offline method. Can be called before authorization //@description Does nothing and ensures that the Update object is used; for testing only. This is an offline method. Can be called before authorization
testUseUpdate = Update; testUseUpdate = Update;
//@description Returns the specified error and ensures that the Error object is used; for testing only. This is an offline method. Can be called before authorization @error The error to be returned //@description Returns the specified error and ensures that the Error object is used; for testing only. This is an offline method. Can be called before authorization. Can be called synchronously @error The error to be returned
testReturnError error:error = Error; testReturnError error:error = Error;

View File

@ -151,7 +151,7 @@ void gen_tl_constructor_from_string(StringBuilder &sb, Slice name, const Vec &ve
sb << "\n };\n"; sb << "\n };\n";
sb << " auto it = m.find(str);\n"; sb << " auto it = m.find(str);\n";
sb << " if (it == m.end()) {\n" sb << " if (it == m.end()) {\n"
<< " return Status::Error(\"Unknown class\");\n" << " return Status::Error(PSLICE() << \"Unknown class \\\"\" << str << \"\\\"\");\n"
<< " }\n" << " }\n"
<< " return it->second;\n"; << " return it->second;\n";
sb << "}\n"; sb << "}\n";

View File

@ -22,11 +22,22 @@
namespace td { namespace td {
static Result<std::pair<td_api::object_ptr<td_api::Function>, string>> to_request(Slice request) { static td_api::object_ptr<td_api::Function> get_return_error_function(Slice error_message) {
auto error = td_api::make_object<td_api::error>(400, error_message.str());
return td_api::make_object<td_api::testReturnError>(std::move(error));
}
static std::pair<td_api::object_ptr<td_api::Function>, string> to_request(Slice request) {
auto request_str = request.str(); auto request_str = request.str();
TRY_RESULT(json_value, json_decode(request_str)); auto r_json_value = json_decode(request_str);
if (r_json_value.is_error()) {
return {get_return_error_function(PSLICE()
<< "Failed to parse request as JSON object: " << r_json_value.error().message()),
string()};
}
auto json_value = r_json_value.move_as_ok();
if (json_value.type() != JsonValue::Type::Object) { if (json_value.type() != JsonValue::Type::Object) {
return Status::Error("Expected an Object"); return {get_return_error_function("Expected a JSON object"), string()};
} }
string extra; string extra;
@ -36,8 +47,13 @@ static Result<std::pair<td_api::object_ptr<td_api::Function>, string>> to_reques
} }
td_api::object_ptr<td_api::Function> func; td_api::object_ptr<td_api::Function> func;
TRY_STATUS(from_json(func, json_value)); auto status = from_json(func, json_value);
return std::make_pair(std::move(func), extra); if (status.is_error()) {
return {get_return_error_function(PSLICE()
<< "Failed to parse JSON object as TDLib request: " << status.error().message()),
std::move(extra)};
}
return std::make_pair(std::move(func), std::move(extra));
} }
static std::string from_response(const td_api::Object &object, const string &extra) { static std::string from_response(const td_api::Object &object, const string &extra) {
@ -62,18 +78,13 @@ static CSlice store_string(std::string str) {
} }
void ClientJson::send(Slice request) { void ClientJson::send(Slice request) {
auto r_request = to_request(request); auto parsed_request = to_request(request);
if (r_request.is_error()) {
LOG(ERROR) << "Failed to parse " << tag("request", format::escaped(request)) << " " << r_request.error();
return;
}
std::uint64_t extra_id = extra_id_.fetch_add(1, std::memory_order_relaxed); std::uint64_t extra_id = extra_id_.fetch_add(1, std::memory_order_relaxed);
if (!r_request.ok_ref().second.empty()) { if (!parsed_request.second.empty()) {
std::lock_guard<std::mutex> guard(mutex_); std::lock_guard<std::mutex> guard(mutex_);
extra_[extra_id] = std::move(r_request.ok_ref().second); extra_[extra_id] = std::move(parsed_request.second);
} }
client_.send(Client::Request{extra_id, std::move(r_request.ok_ref().first)}); client_.send(Client::Request{extra_id, std::move(parsed_request.first)});
} }
CSlice ClientJson::receive(double timeout) { CSlice ClientJson::receive(double timeout) {
@ -95,14 +106,9 @@ CSlice ClientJson::receive(double timeout) {
} }
CSlice ClientJson::execute(Slice request) { CSlice ClientJson::execute(Slice request) {
auto r_request = to_request(request); auto parsed_request = to_request(request);
if (r_request.is_error()) { return store_string(from_response(*Client::execute(Client::Request{0, std::move(parsed_request.first)}).object,
LOG(ERROR) << "Failed to parse " << tag("request", format::escaped(request)) << " " << r_request.error(); parsed_request.second));
return {};
}
return store_string(from_response(*Client::execute(Client::Request{0, std::move(r_request.ok_ref().first)}).object,
r_request.ok().second));
} }
} // namespace td } // namespace td

View File

@ -3422,6 +3422,7 @@ bool Td::is_synchronous_request(int32 id) {
case td_api::setLogTagVerbosityLevel::ID: case td_api::setLogTagVerbosityLevel::ID:
case td_api::getLogTagVerbosityLevel::ID: case td_api::getLogTagVerbosityLevel::ID:
case td_api::addLogMessage::ID: case td_api::addLogMessage::ID:
case td_api::testReturnError::ID:
return true; return true;
default: default:
return false; return false;
@ -3433,7 +3434,6 @@ bool Td::is_preinitialization_request(int32 id) {
case td_api::getCurrentState::ID: case td_api::getCurrentState::ID:
case td_api::setAlarm::ID: case td_api::setAlarm::ID:
case td_api::testUseUpdate::ID: case td_api::testUseUpdate::ID:
case td_api::testReturnError::ID:
case td_api::testCallEmpty::ID: case td_api::testCallEmpty::ID:
case td_api::testSquareInt::ID: case td_api::testSquareInt::ID:
case td_api::testCallString::ID: case td_api::testCallString::ID:
@ -3632,6 +3632,7 @@ td_api::object_ptr<td_api::Object> Td::static_request(td_api::object_ptr<td_api:
case td_api::cleanFileName::ID: case td_api::cleanFileName::ID:
case td_api::getJsonValue::ID: case td_api::getJsonValue::ID:
case td_api::getJsonString::ID: case td_api::getJsonString::ID:
case td_api::testReturnError::ID:
return true; return true;
default: default:
return false; return false;
@ -7664,8 +7665,16 @@ td_api::object_ptr<td_api::Object> Td::do_static_request(const td_api::addLogMes
return td_api::make_object<td_api::ok>(); return td_api::make_object<td_api::ok>();
} }
td_api::object_ptr<td_api::Object> Td::do_static_request(td_api::testReturnError &request) {
if (request.error_ == nullptr) {
return td_api::make_object<td_api::error>(404, "Not Found");
}
return std::move(request.error_);
}
// test // test
void Td::on_request(uint64 id, td_api::testNetwork &request) { void Td::on_request(uint64 id, const td_api::testNetwork &request) {
create_handler<TestQuery>(id)->send(); create_handler<TestQuery>(id)->send();
} }
@ -7677,24 +7686,24 @@ void Td::on_request(uint64 id, td_api::testProxy &request) {
CREATE_REQUEST(TestProxyRequest, r_proxy.move_as_ok()); CREATE_REQUEST(TestProxyRequest, r_proxy.move_as_ok());
} }
void Td::on_request(uint64 id, td_api::testGetDifference &request) { void Td::on_request(uint64 id, const td_api::testGetDifference &request) {
updates_manager_->get_difference("testGetDifference"); updates_manager_->get_difference("testGetDifference");
send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>()); send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>());
} }
void Td::on_request(uint64 id, td_api::testUseUpdate &request) { void Td::on_request(uint64 id, const td_api::testUseUpdate &request) {
send_closure(actor_id(this), &Td::send_result, id, nullptr); send_closure(actor_id(this), &Td::send_result, id, nullptr);
} }
void Td::on_request(uint64 id, td_api::testReturnError &request) { void Td::on_request(uint64 id, const td_api::testReturnError &request) {
send_closure(actor_id(this), &Td::send_result, id, std::move(request.error_)); UNREACHABLE();
} }
void Td::on_request(uint64 id, td_api::testCallEmpty &request) { void Td::on_request(uint64 id, const td_api::testCallEmpty &request) {
send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>()); send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::ok>());
} }
void Td::on_request(uint64 id, td_api::testSquareInt &request) { void Td::on_request(uint64 id, const td_api::testSquareInt &request) {
send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::testInt>(request.x_ * request.x_)); send_closure(actor_id(this), &Td::send_result, id, make_tl_object<td_api::testInt>(request.x_ * request.x_));
} }

View File

@ -1023,13 +1023,13 @@ class Td final : public NetQueryCallback {
void on_request(uint64 id, const td_api::addLogMessage &request); void on_request(uint64 id, const td_api::addLogMessage &request);
// test // test
void on_request(uint64 id, td_api::testNetwork &request); void on_request(uint64 id, const td_api::testNetwork &request);
void on_request(uint64 id, td_api::testProxy &request); void on_request(uint64 id, td_api::testProxy &request);
void on_request(uint64 id, td_api::testGetDifference &request); void on_request(uint64 id, const td_api::testGetDifference &request);
void on_request(uint64 id, td_api::testUseUpdate &request); void on_request(uint64 id, const td_api::testUseUpdate &request);
void on_request(uint64 id, td_api::testReturnError &request); void on_request(uint64 id, const td_api::testReturnError &request);
void on_request(uint64 id, td_api::testCallEmpty &request); void on_request(uint64 id, const td_api::testCallEmpty &request);
void on_request(uint64 id, td_api::testSquareInt &request); void on_request(uint64 id, const td_api::testSquareInt &request);
void on_request(uint64 id, td_api::testCallString &request); void on_request(uint64 id, td_api::testCallString &request);
void on_request(uint64 id, td_api::testCallBytes &request); void on_request(uint64 id, td_api::testCallBytes &request);
void on_request(uint64 id, td_api::testCallVectorInt &request); void on_request(uint64 id, td_api::testCallVectorInt &request);
@ -1058,6 +1058,7 @@ class Td final : public NetQueryCallback {
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::setLogTagVerbosityLevel &request); static td_api::object_ptr<td_api::Object> do_static_request(const td_api::setLogTagVerbosityLevel &request);
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::getLogTagVerbosityLevel &request); static td_api::object_ptr<td_api::Object> do_static_request(const td_api::getLogTagVerbosityLevel &request);
static td_api::object_ptr<td_api::Object> do_static_request(const td_api::addLogMessage &request); static td_api::object_ptr<td_api::Object> do_static_request(const td_api::addLogMessage &request);
static td_api::object_ptr<td_api::Object> do_static_request(td_api::testReturnError &request);
static DbKey as_db_key(string key); static DbKey as_db_key(string key);
Status init(DbKey key) TD_WARN_UNUSED_RESULT; Status init(DbKey key) TD_WARN_UNUSED_RESULT;