#include <memory> #include <string> #include <vector> #include <mutex> // For thread-safe access to 'items' #include <restbed> #include <json/json.h> // You'll need a JSON library like jsoncpp using namespace std; using namespace restbed; // Simple in-memory "database" for demonstration struct Item { int id; string name; // Helper to convert Item to JSON Json::Value toJson() const { Json::Value itemJson; itemJson["id"] = id; itemJson["name"] = name; return itemJson; } }; vector<Item> items = { {1, "Apple"}, {2, "Banana"} }; mutex items_mutex; // Mutex for thread-safe access to 'items' atomic<int> next_item_id(3); // For simple ID generation // Helper to convert vector<Item> to JSON array Json::Value itemsToJson(const vector<Item>& currentItems) { Json::Value itemsArray(Json::arrayValue); for (const auto& item : currentItems) { itemsArray.append(item.toJson()); } return itemsArray; } // GET all items handler void get_all_items_handler(const shared_ptr<Session> session) { lock_guard<mutex> lock(items_mutex); // Lock for read access Json::StreamWriterBuilder writer; string json_string = Json::writeString(writer, itemsToJson(items)); session->close(OK, json_string, { { "Content-Type", "application/json" }, { "Content-Length", to_string(json_string.length()) } }); } // GET item by ID handler void get_item_by_id_handler(const shared_ptr<Session> session) { const auto request = session->get_request(); int id = stod(request->get_path_parameter("id")); lock_guard<mutex> lock(items_mutex); // Lock for read access auto it = find_if(items.begin(), items.end(), [id](const Item& item) { return item.id == id; }); if (it != items.end()) { Json::StreamWriterBuilder writer; string json_string = Json::writeString(writer, it->toJson()); session->close(OK, json_string, { { "Content-Type", "application/json" }, { "Content-Length", to_string(json_string.length()) } }); } else { session->close(NOT_FOUND, "{"message": "Item not found"}", { { "Content-Type", "application/json" }, { "Content-Length", to_string(string("{"message": "Item not found"}").length()) } }); } } // POST new item handler void create_item_handler(const shared_ptr<Session> session) { const auto request = session->get_request(); size_t content_length = request->get_header("Content-Length", 0); session->fetch(content_length, [session, request](const shared_ptr<Session> session, const Bytes& body) { Json::CharReaderBuilder reader; Json::Value root; string errs; if (!Json::parseFromStream(reader, reinterpret_cast<const char*>(body.data()), reinterpret_cast<const char*>(body.data() + body.size()), &root, &errs)) { session->close(BAD_REQUEST, "{"message": "Invalid JSON"}", { { "Content-Type", "application/json" } }); return; } if (root.isMember("name") && root["name"].isString()) { lock_guard<mutex> lock(items_mutex); // Lock for write access Item newItem; newItem.id = next_item_id++; newItem.name = root["name"].asString(); items.push_back(newItem); Json::StreamWriterBuilder writer; string json_string = Json::writeString(writer, newItem.toJson()); session->close(CREATED, json_string, { { "Content-Type", "application/json" }, { "Content-Length", to_string(json_string.length()) } }); } else { session->close(BAD_REQUEST, "{"message": "Name is required"}", { { "Content-Type", "application/json" } }); } }); } // DELETE item by ID handler void delete_item_handler(const shared_ptr<Session> session) { const auto request = session->get_request(); int id = stod(request->get_path_parameter("id")); lock_guard<mutex> lock(items_mutex); // Lock for write access auto initial_size = items.size(); items.erase(remove_if(items.begin(), items.end(), [id](const Item& item) { return item.id == id; }), items.end()); if (items.size() < initial_size) { session->close(NO_CONTENT); // 204 No Content } else { session->close(NOT_FOUND, "{"message": "Item not found"}", { { "Content-Type", "application/json" } }); } } int main() { auto resource_all = make_shared<Resource>(); resource_all->set_path("/items"); resource_all->set_method_handler("GET", get_all_items_handler); resource_all->set_method_handler("POST", create_item_handler); auto resource_by_id = make_shared<Resource>(); resource_by_id->set_path("/items/{id: [0-9]+}"); // Regex for integer ID resource_by_id->set_method_handler("GET", get_item_by_id_handler); resource_by_id->set_method_handler("DELETE", delete_item_handler); // Add PUT if needed auto settings = make_shared<Settings>(); settings->set_port(8080); settings->set_default_header("Connection", "close"); Service service; service.publish(resource_all); service.publish(resource_by_id); service.start(settings); return EXIT_SUCCESS; }
