RESTful
REST全称是Representational State Transfer,通常译为表述性状态转移,是一种网络应用程序的设计风格和开发方式。
它首次出现在2000年Roy Fielding的博士论文中,Roy Fielding是HTTP规范的主要编写者之一。 他在论文中提到:
我这篇文章的写作目的,就是想在符合架构原理的前提下,理解和评估以网络为基础的应用软件的架构设计,得到一个功能强、性能好、适宜通信的架构。REST指的是一组架构约束条件和原则。
如果一个架构符合REST的约束条件和原则,我们就称它为RESTful架构。
REST本身并没有创造新的技术、组件或服务,而隐藏在RESTful背后的理念就是使用Web的现有特征和能力, 更好地使用现有Web标准中的一些准则和约束。
虽然REST本身受Web技术的影响很深, 但是理论上REST架构风格并不是绑定在HTTP上,只不过目前HTTP是唯一与REST相关的实例。 所以我们这里描述的REST也是通过HTTP实现的REST。
进一步介绍请参阅相关资料。
cpprestsdk
Microsoft 的一个开源跨平台项目( 使用 MIT 开源协议 ), 其使用大量现代异步 C++ API 实现了一个基于 HTTP / HTTPS 协议的 服务端 / 客户端 组件,使用该组件,可以方便地进行高性能RESTful、HTTP / HTTPS 服务器、客户端开发,且可以在Windows、Linux、OSX、iOS、Android各平台下使用。
编译与安装
执行下列命令安装:
sudo apt-get install libcpprest-dev
也可以通过git下载源码,进行编译及安装。
官网提供的异步例程
在官网的get started页面,提供了一个简洁的异步示例,列举如下。
该示例将异步地向 http://www.bing.com
发送请求并把结果保存到文件。
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
using namespace utility; // Common utilities like string conversions
using namespace web; // Common features like URIs.
using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // HTTP client features
using namespace concurrency::streams; // Asynchronous streams
int main(int argc, char* argv[])
{
auto fileStream = std::make_shared<ostream>();
// Open stream to output file.
pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
{
*fileStream = outFile;
// Create http_client to send the request.
http_client client(U("http://www.bing.com/"));
// Build request URI and start the request.
uri_builder builder(U("/search"));
builder.append_query(U("q"), U("cpprestsdk github"));
return client.request(methods::GET, builder.to_string());
})
// Handle response headers arriving.
.then([=](http_response response)
{
printf("Received response status code:%u\n", response.status_code());
// Write response body into the file.
return response.body().read_to_end(fileStream->streambuf());
})
// Close the file stream.
.then([=](size_t)
{
return fileStream->close();
});
// Wait for all the outstanding I/O to complete and handle any exceptions
try
{
requestTask.wait();
}
catch (const std::exception &e)
{
printf("Error exception:%s\n", e.what());
}
return 0;
}
同步PUT方式示例
该示例使用Json作为通信方交互格式,使用PUT向服务器发送消息,并等待回应,处理结果。
// 通过参数传入Json体内容
void HandleRestMsg(const std::string &errorName, const std::string &status, const std::string &msg)
{
utility::stringstream_t msgStream;
try
{
json::value reqMsg;
reqMsg[U("service_id")] = json::value::string(U(serverId));
reqMsg[U("error_name")] = json::value::string(U(errorName));
reqMsg[U("business_status")] = json::value::string(U(status));
reqMsg[U("business_message")] = json::value::string(U(msg));
reqMsg.serialize(msgStream);
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
return;
}
try
{
// default timeout is 30s, set to 10s
http_client_config config;
config.set_timeout(utility::seconds(10));
// Create http_client to send the request
http_client client(U(url));
// Build request URI and start the request.
uri_builder builder(U(uri));
// request,同步方式
http_response response = client.request(methods::PUT, builder.to_string(), msgStream.str(), U("application/json")).get();
if (response.status_code() == status_codes::OK)
{
try
{
const json::value &jv = response.extract_json().get();
const web::json::object &jobj = jv.as_object();
auto result_code = jobj.at(U("error_code")).as_integer();
cout << "error code: " << result_code << endl;
}
catch (const std::exception &e)
{
cout << e.what() << endl;
}
}
else
{
cout << "error" << endl;
}
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
}
}
返回的Json简单,为 {“error_code”:错误码 }
。
使用此方式可以实现客户端向服务器进行日志消息的推送。
注意:同步操作会造成程序阻塞,所以应在单独线程中进行。