简介
C++ REST SDK 是 Microsoft 的一个开源跨平台项目( 使用 MIT 开源协议 ), 其使用大量现代异步 C++ API 实现了一个基于 HTTP / HTTPS 协议的 服务端 / 客户端 组件,使用该组件,可以方便地进行高性能RESTful、HTTP / HTTPS 服务器、客户端开发,且可以在Windows、Linux、OSX、iOS、Android各平台下使用,各平台及功能支持情况如下:
平台/功能 | Windows | Linux | Mac OSX | iOS | Android |
---|---|---|---|---|---|
并行任务 | 支持 | 支持 | 支持 | 支持 | 支持 |
JSON编解码 | 支持 | 支持 | 支持 | 支持 | 支持 |
异步流 | 支持 | 支持 | 支持 | 支持 | 支持 |
URIs解析 | 支持 | 支持 | 支持 | 支持 | 支持 |
HTTP客户端 | 支持 | 支持 | 支持 | 支持 | 支持 |
HTTP监听(服务端) | (XP以上支持) | 支持 | 支持 | 支持 | 支持 |
WebSocket客户端 | 支持 | 支持 | 支持 | 支持 | 支持 |
OAuth客户端 | 支持 | 支持 | 支持 | 支持 | 支持 |
Cpp Rest SDK编译
官方推荐使用vcpkg下载CPP Rest SDK源码和编译,该工具除了可以下载Cpp Rest SDK源码外还可自动下载相关依赖包,并通过命令行进行自动编译、向VisualStudio引入相关库,大大简化了在自己的项目中使用Cpp Rest SDK的难度。
vcpkg作为微软开发的另一款开源代码管理工具,并未随Visual Studio 2015安装在系统中,我们需要手动下载该工具源码并进行编译才可以使用:
(1)通过Git下载vcpkg源码到一个文件夹下:
git clone https://github.com/Microsoft/vcpkg
(2)在该文件夹运行命令进行编译:
bootstrap-vcpkg.bat
(3)为了使vcpkg能自动在VS中添加相关库引用,在管理员权限下运行:
vcpkg integrate install
(4)重启命令行,这样vcpkg就安装配置好了
(5)在命令行中使用vcpkg下载CPP Rest SDK源码(注意事项:工作目录不能含有中文、空格,编译需要使用英文版的Visual Studio,否则会编译出错):
vcpkg install cpprestsdk cpprestsdk:x64-windows
(6)在漫长的等待后,命令行提示全部编译完成,此时,就可以打开VS新建一个项目试试效果了,以下是一个简单的HTTP服务器例子:
//main.cpp
#include <iostream>
#include "include/stdafx.h"
#include "include/handler.h"
#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/http_listener.h> // HTTP server
#include <cpprest/json.h> // JSON library
#include <cpprest/uri.h> // URI library
#include <cpprest/ws_client.h> // WebSocket client
#include <cpprest/containerstream.h> // Async streams backed by STL containers
#include <cpprest/interopstream.h> // Bridges for integrating Async streams with STL and WinRT streams
#include <cpprest/rawptrstream.h> // Async streams backed by raw pointer to memory
#include <cpprest/producerconsumerstream.h> // Async streams for producer consumer scenarios
using namespace std;
using namespace web;
using namespace http;
using namespace utility;
using namespace http::experimental::listener;
std::unique_ptr<handler> g_httpHandler;
void on_initialize(const string_t& address)
{
uri_builder uri(address);
auto addr = uri.to_uri().to_string();
g_httpHandler = std::unique_ptr<handler>(new handler(addr));
g_httpHandler->open().wait();
ucout << utility::string_t(U("Listening for requests at: ")) << addr << std::endl;
return;
}
void on_shutdown()
{
g_httpHandler->close().wait();
return;
}
#ifdef _WIN32
int wmain(int argc, wchar_t *argv[])
#else
int main(int argc, char *argv[])
#endif
{
utility::string_t port = U("34568");
if(argc == 2)
{
port = argv[1];
}
utility::string_t address = U("http://127.0.0.1:");
address.append(port);
on_initialize(address);
std::cout << "Press ENTER to exit." << std::endl;
std::string line;
std::getline(std::cin, line);
on_shutdown();
return 0;
}
//hander.h
#ifndef HANDLER_H
#define HANDLER_H
#include <iostream>
#include "stdafx.h"
//#include "../dbms/include/Dbms.h"
using namespace std;
using namespace web;
using namespace http;
using namespace utility;
using namespace http::experimental::listener;
class handler
{
public:
handler();
handler(utility::string_t url);
virtual ~handler();
pplx::task<void>open(){return m_listener.open();}
pplx::task<void>close(){return m_listener.close();}
protected:
private:
void handle_get(http_request message);
void handle_put(http_request message);
void handle_post(http_request message);
void handle_delete(http_request message);
void handle_error(pplx::task<void>& t);
http_listener m_listener;
};
#endif // HANDLER_H
//hander.cpp
#include "../include/handler.h"
handler::handler()
{
//ctor
}
handler::handler(utility::string_t url):m_listener(url)
{
m_listener.support(methods::GET, std::bind(&handler::handle_get, this, std::placeholders::_1));
m_listener.support(methods::PUT, std::bind(&handler::handle_put, this, std::placeholders::_1));
m_listener.support(methods::POST, std::bind(&handler::handle_post, this, std::placeholders::_1));
m_listener.support(methods::DEL, std::bind(&handler::handle_delete, this, std::placeholders::_1));
}
handler::~handler()
{
//dtor
}
void handler::handle_error(pplx::task<void>& t)
{
try
{
t.get();
}
catch(...)
{
// Ignore the error, Log it if a logger is available
}
}
//
// Get Request
//
void handler::handle_get(http_request message)
{
ucout << message.to_string() << endl;
auto paths = http::uri::split_path(http::uri::decode(message.relative_uri().path()));
message.relative_uri().path();
//Dbms* d = new Dbms();
//d->connect();
concurrency::streams::fstream::open_istream(U("static/index.html"), std::ios::in).then([=](concurrency::streams::istream is)
{
message.reply(status_codes::OK, is, U("text/html"))
.then([](pplx::task<void> t)
{
try{
t.get();
}
catch(...){
//
}
});
}).then([=](pplx::task<void>t)
{
try{
t.get();
}
catch(...){
message.reply(status_codes::InternalError,U("INTERNAL ERROR "));
}
});
return;
};
//
// A POST request
//
void handler::handle_post(http_request message)
{
ucout << message.to_string() << endl;
message.reply(status_codes::OK,message.to_string());
return ;
};
//
// A DELETE request
//
void handler::handle_delete(http_request message)
{
ucout << message.to_string() << endl;
wstring rep = U("WRITE YOUR OWN DELETE OPERATION");
message.reply(status_codes::OK,rep);
return;
};
//
// A PUT request
//
void handler::handle_put(http_request message)
{
ucout << message.to_string() << endl;
wstring rep = U("WRITE YOUR OWN PUT OPERATION");
message.reply(status_codes::OK,rep);
return;
};
(7)编译通过后,运行程序,使用浏览器访问如下地址,即可看到服务器已成功运行
http://127.0.0.1:34568
参考链接:
https://github.com/Microsoft/vcpkg
https://github.com/Microsoft/cpprestsdk
https://github.com/Pintulalm/Restweb