Add RestListService and RestDetailService; update README.

This commit is contained in:
Chunting Gu
2018-05-12 19:09:37 +08:00
parent 5e6f125f90
commit 189a246221
10 changed files with 321 additions and 87 deletions
+56 -50
View File
@@ -115,71 +115,77 @@ static bool BookFromJson(const std::string& json, Book* book) {
return true;
}
bool BookListService::Handle(const std::string& http_method,
const std::vector<std::string>& url_sub_matches,
const webcc::UrlQuery& query,
const std::string& request_content,
std::string* response_content) {
if (http_method == webcc::kHttpGet) {
// Return all books as a JSON array.
Json::Value root(Json::arrayValue);
for (const Book& book : g_book_store.books()) {
root.append(book.ToJson());
}
Json::StreamWriterBuilder builder;
*response_content = Json::writeString(builder, root);
return true;
// Return all books as a JSON array.
// TODO: Support query parameters.
bool BookListService::Get(const webcc::UrlQuery& /* query */,
std::string* response_content) {
Json::Value root(Json::arrayValue);
for (const Book& book : g_book_store.books()) {
root.append(book.ToJson());
}
if (http_method == webcc::kHttpPost) {
// Add a new book.
Book book;
if (BookFromJson(request_content, &book)) {
return g_book_store.AddBook(book);
}
return false;
}
Json::StreamWriterBuilder builder;
*response_content = Json::writeString(builder, root);
return true;
}
// Add a new book.
// No response content.
bool BookListService::Post(const std::string& request_content,
std::string* /* response_content */) {
Book book;
if (BookFromJson(request_content, &book)) {
return g_book_store.AddBook(book);
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
bool BookDetailService::Handle(const std::string& http_method,
const std::vector<std::string>& url_sub_matches,
const webcc::UrlQuery& query,
const std::string& request_content,
std::string* response_content) {
bool BookDetailService::Get(const std::vector<std::string>& url_sub_matches,
std::string* response_content) {
if (url_sub_matches.size() != 1) {
return false;
}
const std::string& book_id = url_sub_matches[0];
if (http_method == webcc::kHttpGet) {
const Book& book = g_book_store.GetBook(book_id);
if (!book.IsNull()) {
Json::StreamWriterBuilder builder;
*response_content = Json::writeString(builder, book.ToJson());
return true;
}
return false;
} else if (http_method == webcc::kHttpPost) {
// Update a book.
Book book;
if (BookFromJson(request_content, &book)) {
book.id = book_id;
return g_book_store.UpdateBook(book);
}
return false;
} else if (http_method == webcc::kHttpDelete) {
return g_book_store.DeleteBook(book_id);
const Book& book = g_book_store.GetBook(book_id);
if (!book.IsNull()) {
Json::StreamWriterBuilder builder;
*response_content = Json::writeString(builder, book.ToJson());
return true;
}
return false;
}
// Update a book partially.
bool BookDetailService::Patch(const std::vector<std::string>& url_sub_matches,
const std::string& request_content,
std::string* response_content) {
if (url_sub_matches.size() != 1) {
return false;
}
const std::string& book_id = url_sub_matches[0];
Book book;
if (BookFromJson(request_content, &book)) {
book.id = book_id;
return g_book_store.UpdateBook(book);
}
return false;
}
bool BookDetailService::Delete(const std::vector<std::string>& url_sub_matches) {
if (url_sub_matches.size() != 1) {
return false;
}
const std::string& book_id = url_sub_matches[0];
return g_book_store.DeleteBook(book_id);
}
+23 -29
View File
@@ -3,48 +3,42 @@
#include "webcc/rest_service.h"
// NOTE:
// XxxListService and XxxDetailService are similar to the XxxListView
// and XxxDetailView in Django (a Python web framework).
////////////////////////////////////////////////////////////////////////////////
// List Service handles the HTTP GET and returns the book list based on
// BookListService handles the HTTP GET and returns the book list based on
// query parameters specified in the URL.
// The URL should be like:
// - /books
// - /books?name={BookName}
// The query parameters could be regular expressions.
class BookListService : public webcc::RestService {
public:
BookListService() = default;
~BookListService() override = default;
class BookListService : public webcc::RestListService {
protected:
// Return a list of books based on query parameters.
// URL examples:
// - /books
// - /books?name={BookName}
bool Get(const webcc::UrlQuery& query,
std::string* response_content) final;
bool Handle(const std::string& http_method,
const std::vector<std::string>& url_sub_matches,
const webcc::UrlQuery& query,
const std::string& request_content,
std::string* response_content) override;
// Create a new book.
bool Post(const std::string& request_content,
std::string* response_content) final;
};
////////////////////////////////////////////////////////////////////////////////
// Detail Service handles the following HTTP methods:
// - GET
// - PUT
// - PATCH
// - DELETE
// The URL should be like: /books/{BookID}.
class BookDetailService : public webcc::RestService {
public:
BookDetailService() = default;
~BookDetailService() override = default;
// The URL is like '/books/{BookID}', and the 'url_sub_matches' parameter
// contains the matched book ID.
class BookDetailService : public webcc::RestDetailService {
protected:
bool Get(const std::vector<std::string>& url_sub_matches,
std::string* response_content) final;
bool Handle(const std::string& http_method,
const std::vector<std::string>& url_sub_matches,
const webcc::UrlQuery& query,
const std::string& request_content,
std::string* response_content) override;
bool Patch(const std::vector<std::string>& url_sub_matches,
const std::string& request_content,
std::string* response_content) final;
bool Delete(const std::vector<std::string>& url_sub_matches) final;
};
#endif // BOOK_SERVICE_H_
+1 -1
View File
@@ -30,7 +30,7 @@ int main(int argc, char* argv[]) {
"/books");
server.RegisterService(std::make_shared<BookDetailService>(),
"/books/(\\d+)");
"/book/(\\d+)");
server.Run();