2019/08/14:这篇文章已通过时了。Webcc 已经演化成了一个比较完备的纯 HTTP 程序库。
详见:Webcc: 轻量级 C++ HTTP 程序库git
Webcc 是我本身写的一个 C++ Web Service 程序库,网络通讯基于 Boost Asio,跨平台,轻量、高效。它并不是只是一个玩具,目前正应用于咱们实际的项目,并且还在不断更新和完善。github
Webcc 同时支持客户端和服务端,你能够用它调用已经存在的 Web Service,也能够用它实现本身的 Web Service,且同时支持 REST 和 SOAP 两种方式。web
考虑到用 SOAP 的人愈来愈少,webcc 对 SOAP 的支持能够经过宏 WEBCC_ENABLE_SOAP
在编译时彻底剔除掉。正则表达式
Webcc 内部对 SOAP 消息的包装和解析依赖于 PugiXml。若是禁掉 SOAP,PugiXml 天然也会一并禁掉;若是启用 SOAP,但愿你能承担对 PugiXml 的这一份小小依赖。数据库
对 SOAP 部分的介绍就这么多,具体可见去年的这篇文章:C++ 调用 SOAP Web Service。segmentfault
假定你要提供一个关于图书的 REST Server,提供下面这些操做或接口:网络
前面两个操做能够经过继承 webcc::RestListService
来实现:框架
class BookListService : public webcc::RestListService { protected: // 查询图书(基于某些特定的条件) // GET /books?<query> bool Get(const webcc::UrlQuery& query, std::string* response_content) override; // 添加一本新图书 // POST /books // |request_content| 包含了新图书的数据,为 JSON 格式的字符串 bool Post(const std::string& request_content, std::string* response_content) override; };
其余几个操做,则须要继承自 webcc::RestDetailService
:ide
class BookDetailService : public webcc::RestDetailService { protected: // 获取一本图书的详细信息 bool Get(const std::vector<std::string>& url_sub_matches, const webcc::UrlQuery& query, std::string* response_content) override; // 更新一本图书的信息 bool Put(const std::vector<std::string>& url_sub_matches, const std::string& request_content, std::string* response_content) override; // 删除一本图书 bool Delete(const std::vector<std::string>& url_sub_matches) override; };
在 Python 的 Django 框架中,有几种不一样的视图(View),其中 XxxListView
对应于一列对象,而 XxxDetailView
对应于单个对象。Webcc 的 RestListService
和 RestDetailService
就是参考了 Django 的这一设计。url
对于 RestListService
,URL 通常为复数形式,好比 /books
。对于 GET 请求,就是查询对象,URL 通常会带 query,好比 /books?author=Barnes
;对于 POST 请求,就是建立新对象,信息由 HTTP 请求体携带,通常为 JSON 格式。
对于 RestDetailService
,URL 通常为单数,好比 /book
,而后还要指定对象的 ID,最终的 URL 格式为 /book/{BookID}
,这个 ID 最终能够经过 url_sub_matches
这个参数拿到。RestDetailService
支持 GET、PUT、PATCH 和 DELETE 几种请求,分别对应于获取、更新、部分更新和删除。
下面看一下 BookDetailService::Get()
的实现:
bool BookDetailService::Get(const std::vector<std::string>& url_sub_matches, const webcc::UrlQuery& query, std::string* response_content) { if (url_sub_matches.size() != 1) { return false; } const std::string& book_id = url_sub_matches[0]; // 接下来: // - 经过 book_id 从数据库拿到这个图书, // - 而后把图书信息转换成 JSON 格式的字符串, // - 最后把 JSON 字符串赋值给输出参数 response_content。 }
Service 本身并不能运行,须要把它们绑定到 RestServer
,下面是 main()
里的部分代码:
webcc::RestServer server(8080, 2); server.Bind(std::make_shared<BookListService>(), "/books", false); server.Bind(std::make_shared<BookDetailService>(), "/book/(\\d+)", true); server.Run();
先建立一个 RestServer
对象,端口号为 8080
,后台的工做线程数为 2
。
而后分别建立 BookListService
和 BookDetailService
,都用 std::shared_ptr
来自动管理对象生命期。
最后绑定 services 到特定的 URL,其中 BookDetailService
的 URL 是一个正则表达式,(\\d+)
最后匹配下来的部分就存在参数 url_sub_matches
中。