Refine REST support; add demo for REST client and server.
This commit is contained in:
@@ -14,4 +14,6 @@ if(WEBCC_ENABLE_DEMO)
|
|||||||
add_subdirectory(demo/soap/calc_client)
|
add_subdirectory(demo/soap/calc_client)
|
||||||
add_subdirectory(demo/soap/calc_server)
|
add_subdirectory(demo/soap/calc_server)
|
||||||
endif()
|
endif()
|
||||||
|
add_subdirectory(demo/rest/book_client)
|
||||||
|
add_subdirectory(demo/rest/book_server)
|
||||||
endif()
|
endif()
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
file(GLOB SRCS *.cc *.h)
|
||||||
|
|
||||||
|
add_executable(rest_book_client ${SRCS})
|
||||||
|
|
||||||
|
target_link_libraries(rest_book_client webcc)
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#include "book_client.h"
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef BOOK_CLIENT_H_
|
||||||
|
#define BOOK_CLIENT_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#endif // BOOK_CLIENT_H_
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "boost/lexical_cast.hpp"
|
||||||
|
|
||||||
|
#include "webcc/http_client.h"
|
||||||
|
#include "webcc/http_request.h"
|
||||||
|
#include "webcc/http_response.h"
|
||||||
|
|
||||||
|
class BookListClient {
|
||||||
|
public:
|
||||||
|
BookListClient() {
|
||||||
|
host_ = "localhost";
|
||||||
|
port_ = "8080";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ListBooks() {
|
||||||
|
webcc::HttpRequest http_request;
|
||||||
|
|
||||||
|
http_request.set_method(webcc::kHttpGet);
|
||||||
|
http_request.set_url("/books");
|
||||||
|
http_request.SetHost(host_, port_);
|
||||||
|
|
||||||
|
http_request.Build();
|
||||||
|
|
||||||
|
webcc::HttpResponse http_response;
|
||||||
|
|
||||||
|
webcc::HttpClient http_client;
|
||||||
|
webcc::Error error = http_client.SendRequest(http_request, &http_response);
|
||||||
|
|
||||||
|
if (error != webcc::kNoError) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Book list: " << std::endl
|
||||||
|
<< http_response.content() << std::endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string host_;
|
||||||
|
std::string port_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BookDetailClient {
|
||||||
|
public:
|
||||||
|
BookDetailClient() {
|
||||||
|
host_ = "localhost";
|
||||||
|
port_ = "8080";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetBook(const std::string& id) {
|
||||||
|
webcc::HttpRequest http_request;
|
||||||
|
|
||||||
|
http_request.set_method(webcc::kHttpGet);
|
||||||
|
http_request.set_url("/books/" + id);
|
||||||
|
http_request.SetHost(host_, port_);
|
||||||
|
|
||||||
|
http_request.Build();
|
||||||
|
|
||||||
|
webcc::HttpResponse http_response;
|
||||||
|
|
||||||
|
webcc::HttpClient http_client;
|
||||||
|
webcc::Error error = http_client.SendRequest(http_request, &http_response);
|
||||||
|
|
||||||
|
if (error != webcc::kNoError) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Book: " << id << std::endl
|
||||||
|
<< http_response.content() << std::endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string host_;
|
||||||
|
std::string port_;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
BookListClient book_list_client;
|
||||||
|
book_list_client.ListBooks();
|
||||||
|
|
||||||
|
BookDetailClient book_detail_client;
|
||||||
|
book_detail_client.GetBook("1");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
file(GLOB SRCS *.cc *.h)
|
||||||
|
|
||||||
|
add_executable(rest_book_server ${SRCS})
|
||||||
|
|
||||||
|
target_link_libraries(rest_book_server webcc)
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
#include "book_services.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include "boost/lexical_cast.hpp"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class Book {
|
||||||
|
public:
|
||||||
|
std::string id;
|
||||||
|
std::string title;
|
||||||
|
double price;
|
||||||
|
|
||||||
|
bool IsNull() const {
|
||||||
|
return id.empty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Book kNullBook{};
|
||||||
|
|
||||||
|
class BookStore {
|
||||||
|
public:
|
||||||
|
BookStore() {
|
||||||
|
books_.push_back({ "1", "Title1", 11.1 });
|
||||||
|
books_.push_back({ "2", "Title2", 22.2 });
|
||||||
|
books_.push_back({ "3", "Title3", 33.3 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::list<Book>& books() const {
|
||||||
|
return books_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Book& GetBook(const std::string& id) const {
|
||||||
|
auto it = std::find_if(books_.begin(),
|
||||||
|
books_.end(),
|
||||||
|
[&id](const Book& book) { return book.id == id; });
|
||||||
|
|
||||||
|
if (it == books_.end()) {
|
||||||
|
return kNullBook;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddBook(const Book& new_book) {
|
||||||
|
auto it = std::find_if(
|
||||||
|
books_.begin(),
|
||||||
|
books_.end(),
|
||||||
|
[&new_book](const Book& book) { return book.id == new_book.id; });
|
||||||
|
|
||||||
|
if (it != books_.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
books_.push_back(new_book);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeleteBook(const std::string& id) {
|
||||||
|
auto it = std::find_if(books_.begin(),
|
||||||
|
books_.end(),
|
||||||
|
[&id](const Book& book) { return book.id == id; });
|
||||||
|
|
||||||
|
if (it == books_.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
books_.erase(it);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::list<Book> books_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static BookStore g_book_store;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Naively create JSON object string for a book.
|
||||||
|
// You should use real JSON library in your product code.
|
||||||
|
static std::string CreateBookJson(const Book& book) {
|
||||||
|
std::string json = "{ ";
|
||||||
|
json += "\"id\": " + book.id + ", ";
|
||||||
|
json += "\"title\": " + book.title + ", ";
|
||||||
|
json += "\"price\": " + std::to_string(book.price);
|
||||||
|
json += " }";
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BookListService::Handle(const std::string& http_method,
|
||||||
|
const std::vector<std::string>& url_sub_matches,
|
||||||
|
const std::string& request_content,
|
||||||
|
std::string* response_content) {
|
||||||
|
if (http_method == webcc::kHttpGet) {
|
||||||
|
*response_content = "{ ";
|
||||||
|
for (const Book& book : g_book_store.books()) {
|
||||||
|
*response_content += CreateBookJson(book);
|
||||||
|
*response_content += ",";
|
||||||
|
}
|
||||||
|
*response_content += " }";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool BookDetailService::Handle(const std::string& http_method,
|
||||||
|
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];
|
||||||
|
|
||||||
|
if (http_method == webcc::kHttpGet) {
|
||||||
|
const Book& book = g_book_store.GetBook(book_id);
|
||||||
|
|
||||||
|
if (book.IsNull()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*response_content = CreateBookJson(book);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else if (http_method == webcc::kHttpPost) {
|
||||||
|
|
||||||
|
} else if (http_method == webcc::kHttpDelete) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef BOOK_SERVICES_H_
|
||||||
|
#define BOOK_SERVICES_H_
|
||||||
|
|
||||||
|
#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
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
bool Handle(const std::string& http_method,
|
||||||
|
const std::vector<std::string>& url_sub_matches,
|
||||||
|
const std::string& request_content,
|
||||||
|
std::string* response_content) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
bool Handle(const std::string& http_method,
|
||||||
|
const std::vector<std::string>& url_sub_matches,
|
||||||
|
const std::string& request_content,
|
||||||
|
std::string* response_content) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BOOK_SERVICE_H_
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "webcc/rest_server.h"
|
||||||
|
#include "book_services.h"
|
||||||
|
|
||||||
|
static void Help(const char* argv0) {
|
||||||
|
std::cout << "Usage: " << argv0 << " <port>" << std::endl;
|
||||||
|
std::cout << " E.g.," << std::endl;
|
||||||
|
std::cout << " " << argv0 << " 8080" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char* argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
Help(argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned short port = std::atoi(argv[1]);
|
||||||
|
|
||||||
|
std::size_t workers = 2;
|
||||||
|
|
||||||
|
try {
|
||||||
|
webcc::RestServer server(port, workers);
|
||||||
|
|
||||||
|
server.RegisterService(std::make_shared<BookListService>(),
|
||||||
|
"/books");
|
||||||
|
|
||||||
|
server.RegisterService(std::make_shared<BookDetailService>(),
|
||||||
|
"/books/(\\d+)");
|
||||||
|
|
||||||
|
server.Run();
|
||||||
|
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
std::cerr << "Exception: " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ public:
|
|||||||
start_line_ = start_line;
|
start_line_ = start_line;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t content_length() const {
|
std::size_t content_length() const {
|
||||||
return content_length_;
|
return content_length_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ public:
|
|||||||
SetHeader(kContentType, content_type);
|
SetHeader(kContentType, content_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetContentLength(size_t content_length) {
|
void SetContentLength(std::size_t content_length) {
|
||||||
content_length_ = content_length;
|
content_length_ = content_length;
|
||||||
SetHeader(kContentLength, std::to_string(content_length));
|
SetHeader(kContentLength, std::to_string(content_length));
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
content_ = std::move(content);
|
content_ = std::move(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppendContent(const char* data, size_t count) {
|
void AppendContent(const char* data, std::size_t count) {
|
||||||
content_.append(data, count);
|
content_.append(data, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +62,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IsContentFull() const {
|
bool IsContentFull() const {
|
||||||
assert(IsContentLengthValid());
|
return IsContentLengthValid() && content_.length() >= content_length_;
|
||||||
return content_.length() >= content_length_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsContentLengthValid() const {
|
bool IsContentLengthValid() const {
|
||||||
|
|||||||
@@ -10,11 +10,12 @@ namespace webcc {
|
|||||||
HttpParser::HttpParser(HttpMessage* message)
|
HttpParser::HttpParser(HttpMessage* message)
|
||||||
: message_(message)
|
: message_(message)
|
||||||
, start_line_parsed_(false)
|
, start_line_parsed_(false)
|
||||||
|
, content_length_parsed_(false)
|
||||||
, header_parsed_(false)
|
, header_parsed_(false)
|
||||||
, finished_(false) {
|
, finished_(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Error HttpParser::Parse(const char* data, size_t len) {
|
Error HttpParser::Parse(const char* data, std::size_t len) {
|
||||||
if (header_parsed_) {
|
if (header_parsed_) {
|
||||||
// Add the data to the content.
|
// Add the data to the content.
|
||||||
message_->AppendContent(data, len);
|
message_->AppendContent(data, len);
|
||||||
@@ -28,10 +29,10 @@ Error HttpParser::Parse(const char* data, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pending_data_.append(data, len);
|
pending_data_.append(data, len);
|
||||||
size_t off = 0;
|
std::size_t off = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
size_t pos = pending_data_.find("\r\n", off);
|
std::size_t pos = pending_data_.find("\r\n", off);
|
||||||
if (pos == std::string::npos) {
|
if (pos == std::string::npos) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -52,8 +53,8 @@ Error HttpParser::Parse(const char* data, size_t len) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Currently, only Content-Length is important to us.
|
// Currently, only Content-Length is important to us.
|
||||||
// Other fields are ignored.
|
// Other header fields are ignored.
|
||||||
if (!message_->IsContentLengthValid()) {
|
if (!content_length_parsed_) {
|
||||||
ParseContentLength(line);
|
ParseContentLength(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,10 +65,17 @@ Error HttpParser::Parse(const char* data, size_t len) {
|
|||||||
if (header_parsed_) {
|
if (header_parsed_) {
|
||||||
// Headers just ended.
|
// Headers just ended.
|
||||||
|
|
||||||
|
if (!content_length_parsed_) {
|
||||||
|
// No Content-Length, no content.
|
||||||
|
message_->SetContentLength(0);
|
||||||
|
finished_ = true;
|
||||||
|
return kNoError;
|
||||||
|
} else {
|
||||||
|
// Invalid Content-Length in the request.
|
||||||
if (!message_->IsContentLengthValid()) {
|
if (!message_->IsContentLengthValid()) {
|
||||||
// No Content-Length?
|
|
||||||
return kHttpContentLengthError;
|
return kHttpContentLengthError;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message_->AppendContent(pending_data_.substr(off));
|
message_->AppendContent(pending_data_.substr(off));
|
||||||
|
|
||||||
@@ -84,7 +92,7 @@ Error HttpParser::Parse(const char* data, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void HttpParser::ParseContentLength(const std::string& line) {
|
void HttpParser::ParseContentLength(const std::string& line) {
|
||||||
size_t pos = line.find(':');
|
std::size_t pos = line.find(':');
|
||||||
if (pos == std::string::npos) {
|
if (pos == std::string::npos) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -92,6 +100,8 @@ void HttpParser::ParseContentLength(const std::string& line) {
|
|||||||
std::string name = line.substr(0, pos);
|
std::string name = line.substr(0, pos);
|
||||||
|
|
||||||
if (boost::iequals(name, kContentLength)) {
|
if (boost::iequals(name, kContentLength)) {
|
||||||
|
content_length_parsed_ = true;
|
||||||
|
|
||||||
++pos; // Skip ':'.
|
++pos; // Skip ':'.
|
||||||
while (line[pos] == ' ') { // Skip spaces.
|
while (line[pos] == ' ') { // Skip spaces.
|
||||||
++pos;
|
++pos;
|
||||||
@@ -100,9 +110,9 @@ void HttpParser::ParseContentLength(const std::string& line) {
|
|||||||
std::string value = line.substr(pos);
|
std::string value = line.substr(pos);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
message_->SetContentLength(boost::lexical_cast<size_t>(value));
|
std::size_t length = boost::lexical_cast<std::size_t>(value);
|
||||||
|
message_->SetContentLength(length);
|
||||||
} catch (boost::bad_lexical_cast&) {
|
} catch (boost::bad_lexical_cast&) {
|
||||||
// TODO
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public:
|
|||||||
return finished_;
|
return finished_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error Parse(const char* data, size_t len);
|
Error Parse(const char* data, std::size_t len);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Parse HTTP start line.
|
// Parse HTTP start line.
|
||||||
@@ -36,6 +36,7 @@ protected:
|
|||||||
|
|
||||||
// Parsing helper flags.
|
// Parsing helper flags.
|
||||||
bool start_line_parsed_;
|
bool start_line_parsed_;
|
||||||
|
bool content_length_parsed_;
|
||||||
bool header_parsed_;
|
bool header_parsed_;
|
||||||
bool finished_;
|
bool finished_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ void HttpRequest::SetHost(const std::string& host, const std::string& port) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpRequest::MakeStartLine() {
|
void HttpRequest::Build() {
|
||||||
if (start_line_.empty()) {
|
if (start_line_.empty()) {
|
||||||
start_line_ = method_;
|
start_line_ = method_;
|
||||||
start_line_ += " ";
|
start_line_ += " ";
|
||||||
@@ -48,7 +48,6 @@ const char CRLF[] = { '\r', '\n' };
|
|||||||
// ATTENTION: The buffers don't hold the memory!
|
// ATTENTION: The buffers don't hold the memory!
|
||||||
std::vector<boost::asio::const_buffer> HttpRequest::ToBuffers() const {
|
std::vector<boost::asio::const_buffer> HttpRequest::ToBuffers() const {
|
||||||
assert(!start_line_.empty());
|
assert(!start_line_.empty());
|
||||||
assert(IsContentLengthValid());
|
|
||||||
|
|
||||||
std::vector<boost::asio::const_buffer> buffers;
|
std::vector<boost::asio::const_buffer> buffers;
|
||||||
|
|
||||||
@@ -63,7 +62,9 @@ std::vector<boost::asio::const_buffer> HttpRequest::ToBuffers() const {
|
|||||||
|
|
||||||
buffers.push_back(boost::asio::buffer(misc_strings::CRLF));
|
buffers.push_back(boost::asio::buffer(misc_strings::CRLF));
|
||||||
|
|
||||||
|
if (content_length_ > 0) {
|
||||||
buffers.push_back(boost::asio::buffer(content_));
|
buffers.push_back(boost::asio::buffer(content_));
|
||||||
|
}
|
||||||
|
|
||||||
return buffers;
|
return buffers;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ public:
|
|||||||
// \param port Numeric port number, "80" will be used if it's empty.
|
// \param port Numeric port number, "80" will be used if it's empty.
|
||||||
void SetHost(const std::string& host, const std::string& port);
|
void SetHost(const std::string& host, const std::string& port);
|
||||||
|
|
||||||
// Compose start line from method, url, etc.
|
// Compose start line, etc.
|
||||||
void MakeStartLine();
|
// Must be called before ToBuffers()!
|
||||||
|
void Build();
|
||||||
|
|
||||||
// Convert the response into a vector of buffers. The buffers do not own the
|
// Convert the response into a vector of buffers. The buffers do not own the
|
||||||
// underlying memory blocks, therefore the request object must remain valid
|
// underlying memory blocks, therefore the request object must remain valid
|
||||||
// and not be changed until the write operation has completed.
|
// and not be changed until the write operation has completed.
|
||||||
// NOTE: Please call MakeStartLine() before.
|
|
||||||
std::vector<boost::asio::const_buffer> ToBuffers() const;
|
std::vector<boost::asio::const_buffer> ToBuffers() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ HttpStatus::Enum RestRequestHandler::HandleSession(HttpSessionPtr session) {
|
|||||||
// TODO: Error handling.
|
// TODO: Error handling.
|
||||||
std::string content;
|
std::string content;
|
||||||
service->Handle(session->request().method(),
|
service->Handle(session->request().method(),
|
||||||
|
sub_matches,
|
||||||
session->request().content(),
|
session->request().content(),
|
||||||
&content);
|
&content);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#ifndef WEBCC_REST_SERVICE_H_
|
#ifndef WEBCC_REST_SERVICE_H_
|
||||||
#define WEBCC_REST_SERVICE_H_
|
#define WEBCC_REST_SERVICE_H_
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "webcc/common.h"
|
#include "webcc/common.h"
|
||||||
|
|
||||||
@@ -18,8 +19,9 @@ public:
|
|||||||
// Both the request and response parameters should be JSON.
|
// Both the request and response parameters should be JSON.
|
||||||
// TODO: Query parameters.
|
// TODO: Query parameters.
|
||||||
virtual bool Handle(const std::string& http_method,
|
virtual bool Handle(const std::string& http_method,
|
||||||
const std::string& request,
|
const std::vector<std::string>& url_sub_matches,
|
||||||
std::string* response) = 0;
|
const std::string& request_content,
|
||||||
|
std::string* response_content) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<RestService> RestServicePtr;
|
typedef std::shared_ptr<RestService> RestServicePtr;
|
||||||
|
|||||||
Reference in New Issue
Block a user