From 93b1d2d1cb28f04a407d40e067757fd987591a97 Mon Sep 17 00:00:00 2001 From: Kishore Nallan Date: Sat, 24 Oct 2020 15:43:55 +0530 Subject: [PATCH] Refactor to a create/update/upsert API model. --- include/core_api.h | 2 +- include/http_server.h | 2 ++ src/core_api.cpp | 41 +++++++++++++++++++++-------------- src/http_server.cpp | 7 ++++++ src/main/typesense_server.cpp | 2 +- 5 files changed, 36 insertions(+), 18 deletions(-) diff --git a/include/core_api.h b/include/core_api.h index e5b00fca..713e5dc1 100644 --- a/include/core_api.h +++ b/include/core_api.h @@ -23,7 +23,7 @@ bool get_export_documents(http_req& req, http_res& res); bool post_add_document(http_req& req, http_res& res); -bool put_upsert_document(http_req& req, http_res& res); +bool patch_update_document(http_req& req, http_res& res); bool post_import_documents(http_req& req, http_res& res); diff --git a/include/http_server.h b/include/http_server.h index 0a30e4b5..847cecef 100644 --- a/include/http_server.h +++ b/include/http_server.h @@ -127,6 +127,8 @@ public: void put(const std::string & path, bool (*handler)(http_req & req, http_res & res), bool async_req=false, bool async_res=false); + void patch(const std::string & path, bool (*handler)(http_req & req, http_res & res), bool async_req=false, bool async_res=false); + void del(const std::string & path, bool (*handler)(http_req & req, http_res & res), bool async_req=false, bool async_res=false); void on(const std::string & message, bool (*handler)(void*)); diff --git a/src/core_api.cpp b/src/core_api.cpp index f163af36..4d4b1f7d 100644 --- a/src/core_api.cpp +++ b/src/core_api.cpp @@ -27,6 +27,18 @@ bool handle_authentication(std::map& req_params, const return collectionManager.auth_key_matches(auth_key, rpath.action, collection, req_params); } +index_operation_t get_index_operation(const std::string& action) { + if(action == "create") { + return CREATE; + } else if(action == "update") { + return UPDATE; + } else if(action == "upsert") { + return UPSERT; + } + + return CREATE; +} + bool get_collections(http_req & req, http_res & res) { CollectionManager & collectionManager = CollectionManager::get_instance(); std::vector collections = collectionManager.get_collections(); @@ -592,14 +604,14 @@ bool post_import_documents(http_req& req, http_res& res) { //LOG(INFO) << "post_import_documents"; //LOG(INFO) << "req.first_chunk=" << req.first_chunk_aggregate << ", last_chunk=" << req.last_chunk_aggregate; const char *BATCH_SIZE = "batch_size"; - const char *UPSERT = "upsert"; + const char *ACTION = "action"; if(req.params.count(BATCH_SIZE) == 0) { req.params[BATCH_SIZE] = "40"; } - if(req.params.count(UPSERT) == 0) { - req.params[UPSERT] = "false"; + if(req.params.count(ACTION) == 0) { + req.params[ACTION] = "create"; } if(!StringUtils::is_uint32_t(req.params[BATCH_SIZE])) { @@ -610,16 +622,15 @@ bool post_import_documents(http_req& req, http_res& res) { return false; } - if(!StringUtils::is_bool(req.params[UPSERT])) { + if(req.params[ACTION] != "create" || req.params[ACTION] != "update" || req.params[ACTION] != "upsert") { req.last_chunk_aggregate = true; res.final = true; - res.set_400("Parameter `" + std::string(UPSERT) + "` must be a boolean."); + res.set_400("Parameter `" + std::string(ACTION) + "` must be a create|update|upsert."); HttpServer::stream_response(req, res); return false; } const size_t IMPORT_BATCH_SIZE = std::stoi(req.params[BATCH_SIZE]); - const bool upsert = (req.params[UPSERT] == "true"); if(IMPORT_BATCH_SIZE == 0) { res.set_400("Parameter `" + std::string(BATCH_SIZE) + "` must be a positive integer."); @@ -694,7 +705,7 @@ bool post_import_documents(http_req& req, http_res& res) { //LOG(INFO) << "single_partial_record_body: " << single_partial_record_body; - const index_operation_t operation = upsert ? index_operation_t::UPSERT : index_operation_t::CREATE; + const index_operation_t operation = get_index_operation(req.params[ACTION]); if(!single_partial_record_body) { nlohmann::json document; @@ -728,18 +739,16 @@ bool post_import_documents(http_req& req, http_res& res) { } bool post_add_document(http_req & req, http_res & res) { - const char *UPSERT = "upsert"; - if(req.params.count(UPSERT) == 0) { - req.params[UPSERT] = "false"; + const char *ACTION = "action"; + if(req.params.count(ACTION) == 0) { + req.params[ACTION] = "create"; } - if(!StringUtils::is_bool(req.params[UPSERT])) { - res.set_400("Parameter `" + std::string(UPSERT) + "` must be a boolean."); + if(req.params[ACTION] != "create" || req.params[ACTION] != "update" || req.params[ACTION] != "upsert") { + res.set_400("Parameter `" + std::string(ACTION) + "` must be a create|update|upsert."); return false; } - const bool upsert = (req.params[UPSERT] == "true"); - CollectionManager & collectionManager = CollectionManager::get_instance(); Collection* collection = collectionManager.get_collection(req.params["collection"]); @@ -748,7 +757,7 @@ bool post_add_document(http_req & req, http_res & res) { return false; } - index_operation_t operation = upsert ? index_operation_t::UPSERT : index_operation_t::CREATE; + const index_operation_t operation = get_index_operation(req.params[ACTION]); Option inserted_doc_op = collection->add(req.body, operation); if(!inserted_doc_op.ok()) { @@ -760,7 +769,7 @@ bool post_add_document(http_req & req, http_res & res) { return true; } -bool put_upsert_document(http_req & req, http_res & res) { +bool patch_update_document(http_req & req, http_res & res) { std::string doc_id = req.params["id"]; CollectionManager & collectionManager = CollectionManager::get_instance(); diff --git a/src/http_server.cpp b/src/http_server.cpp index 11e750ea..9d9a035a 100644 --- a/src/http_server.cpp +++ b/src/http_server.cpp @@ -706,6 +706,13 @@ void HttpServer::put(const std::string & path, bool (*handler)(http_req &, http_ routes.emplace_back(rpath.route_hash(), rpath); } +void HttpServer::patch(const std::string & path, bool (*handler)(http_req &, http_res &), bool async_req, bool async_res) { + std::vector path_parts; + StringUtils::split(path, path_parts, "/"); + route_path rpath("PATCH", path_parts, handler, async_req, async_res); + routes.emplace_back(rpath.route_hash(), rpath); +} + void HttpServer::del(const std::string & path, bool (*handler)(http_req &, http_res &), bool async_req, bool async_res) { std::vector path_parts; StringUtils::split(path, path_parts, "/"); diff --git a/src/main/typesense_server.cpp b/src/main/typesense_server.cpp index a0caf2fc..28e2cd79 100644 --- a/src/main/typesense_server.cpp +++ b/src/main/typesense_server.cpp @@ -21,7 +21,7 @@ void master_server_routes() { // document management - `/documents/:id` end-points must be placed last in the list server->post("/collections/:collection/documents", post_add_document); - server->put("/collections/:collection/documents/:id", put_upsert_document); + server->patch("/collections/:collection/documents/:id", patch_update_document); server->get("/collections/:collection/documents/search", get_search); server->post("/collections/:collection/documents/import", post_import_documents, true, true);