在卡萨布兰卡实施多个 API
Implementing multiple API in casablanca
我正在查看这段代码,它使用 casablanca 实现了一个简单的 JSON 服务器。到目前为止,我还没有找到更好的例子。作者似乎对每个 API 使用了不同的 HTTP 方法,当服务器应该有很多 API 时,这可能会成为一个问题。应该如何解决这个问题?这是否意味着我需要多个 http_listeners ?
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
#include <iostream>
#include <map>
#include <set>
#include <string>
using namespace std;
#define TRACE(msg) wcout << msg
#define TRACE_ACTION(a, k, v) wcout << a << L" (" << k << L", " << v << L")\n"
map<utility::string_t, utility::string_t> dictionary;
typedef std::vector<std::pair<utility::string_t, json::value>> field_map;
/* handlers implementation */
void handle_get(http_request request)
{
TRACE(L"\nhandle GET\n");
field_map answer;
for (auto const & p : dictionary)
{
answer.push_back(make_pair(p.first, json::value(p.second)));
}
request.reply(status_codes::OK, json::value::object(answer));
}
void handle_request(http_request request,
function<void(json::value &, field_map &)> action)
{
field_map answer;
request
.extract_json()
.then([&answer, &action](pplx::task<json::value> task) {
try
{
auto & jvalue = task.get();
if (!jvalue.is_null())
{
action(jvalue, answer);
}
}
catch (http_exception const & e)
{
wcout << e.what() << endl;
}
})
.wait();
request.reply(status_codes::OK, json::value::object(answer));
}
void handle_post(http_request request)
{
TRACE("\nhandle POST\n");
handle_request(
request,
[](json::value & jvalue, field_map & answer)
{
for (auto const & e : jvalue.as_array())
{
if (e.is_string())
{
auto key = e.as_string();
auto pos = dictionary.find(key);
if (pos == dictionary.end())
{
answer.push_back(make_pair(key, json::value(L"<nil>")));
}
else
{
answer.push_back(make_pair(pos->first, json::value(pos->second)));
}
}
}
}
);
}
void handle_put(http_request request)
{
TRACE("\nhandle PUT\n");
handle_request(
request,
[](json::value & jvalue, field_map & answer)
{
for (auto const & e : jvalue.as_object())
{
if (e.second.is_string())
{
auto key = e.first;
auto value = e.second.as_string();
if (dictionary.find(key) == dictionary.end())
{
TRACE_ACTION(L"added", key, value);
answer.push_back(make_pair(key, json::value(L"<put>")));
}
else
{
TRACE_ACTION(L"updated", key, value);
answer.push_back(make_pair(key, json::value(L"<updated>")));
}
dictionary[key] = value;
}
}
}
);
}
void handle_del(http_request request)
{
TRACE("\nhandle DEL\n");
handle_request(
request,
[](json::value & jvalue, field_map & answer)
{
set<utility::string_t> keys;
for (auto const & e : jvalue.as_array())
{
if (e.is_string())
{
auto key = e.as_string();
auto pos = dictionary.find(key);
if (pos == dictionary.end())
{
answer.push_back(make_pair(key, json::value(L"<failed>")));
}
else
{
TRACE_ACTION(L"deleted", pos->first, pos->second);
answer.push_back(make_pair(key, json::value(L"<deleted>")));
keys.insert(key);
}
}
}
for (auto const & key : keys)
dictionary.erase(key);
}
);
}
int main()
{
http_listener listener(L"http://localhost/restdemo");
listener.support(methods::GET, handle_get);
listener.support(methods::POST, handle_post);
listener.support(methods::PUT, handle_put);
listener.support(methods::DEL, handle_del);
try
{
listener
.open()
.then([&listener]() {TRACE(L"\nstarting to listen\n"); })
.wait();
while (true);
}
catch (exception const & e)
{
wcout << e.what() << endl;
}
return 0;
}
是的,您可以根据 URI 设置多个 http_listeners。效果很好。
我正在查看这段代码,它使用 casablanca 实现了一个简单的 JSON 服务器。到目前为止,我还没有找到更好的例子。作者似乎对每个 API 使用了不同的 HTTP 方法,当服务器应该有很多 API 时,这可能会成为一个问题。应该如何解决这个问题?这是否意味着我需要多个 http_listeners ?
#include <cpprest/http_listener.h>
#include <cpprest/json.h>
using namespace web;
using namespace web::http;
using namespace web::http::experimental::listener;
#include <iostream>
#include <map>
#include <set>
#include <string>
using namespace std;
#define TRACE(msg) wcout << msg
#define TRACE_ACTION(a, k, v) wcout << a << L" (" << k << L", " << v << L")\n"
map<utility::string_t, utility::string_t> dictionary;
typedef std::vector<std::pair<utility::string_t, json::value>> field_map;
/* handlers implementation */
void handle_get(http_request request)
{
TRACE(L"\nhandle GET\n");
field_map answer;
for (auto const & p : dictionary)
{
answer.push_back(make_pair(p.first, json::value(p.second)));
}
request.reply(status_codes::OK, json::value::object(answer));
}
void handle_request(http_request request,
function<void(json::value &, field_map &)> action)
{
field_map answer;
request
.extract_json()
.then([&answer, &action](pplx::task<json::value> task) {
try
{
auto & jvalue = task.get();
if (!jvalue.is_null())
{
action(jvalue, answer);
}
}
catch (http_exception const & e)
{
wcout << e.what() << endl;
}
})
.wait();
request.reply(status_codes::OK, json::value::object(answer));
}
void handle_post(http_request request)
{
TRACE("\nhandle POST\n");
handle_request(
request,
[](json::value & jvalue, field_map & answer)
{
for (auto const & e : jvalue.as_array())
{
if (e.is_string())
{
auto key = e.as_string();
auto pos = dictionary.find(key);
if (pos == dictionary.end())
{
answer.push_back(make_pair(key, json::value(L"<nil>")));
}
else
{
answer.push_back(make_pair(pos->first, json::value(pos->second)));
}
}
}
}
);
}
void handle_put(http_request request)
{
TRACE("\nhandle PUT\n");
handle_request(
request,
[](json::value & jvalue, field_map & answer)
{
for (auto const & e : jvalue.as_object())
{
if (e.second.is_string())
{
auto key = e.first;
auto value = e.second.as_string();
if (dictionary.find(key) == dictionary.end())
{
TRACE_ACTION(L"added", key, value);
answer.push_back(make_pair(key, json::value(L"<put>")));
}
else
{
TRACE_ACTION(L"updated", key, value);
answer.push_back(make_pair(key, json::value(L"<updated>")));
}
dictionary[key] = value;
}
}
}
);
}
void handle_del(http_request request)
{
TRACE("\nhandle DEL\n");
handle_request(
request,
[](json::value & jvalue, field_map & answer)
{
set<utility::string_t> keys;
for (auto const & e : jvalue.as_array())
{
if (e.is_string())
{
auto key = e.as_string();
auto pos = dictionary.find(key);
if (pos == dictionary.end())
{
answer.push_back(make_pair(key, json::value(L"<failed>")));
}
else
{
TRACE_ACTION(L"deleted", pos->first, pos->second);
answer.push_back(make_pair(key, json::value(L"<deleted>")));
keys.insert(key);
}
}
}
for (auto const & key : keys)
dictionary.erase(key);
}
);
}
int main()
{
http_listener listener(L"http://localhost/restdemo");
listener.support(methods::GET, handle_get);
listener.support(methods::POST, handle_post);
listener.support(methods::PUT, handle_put);
listener.support(methods::DEL, handle_del);
try
{
listener
.open()
.then([&listener]() {TRACE(L"\nstarting to listen\n"); })
.wait();
while (true);
}
catch (exception const & e)
{
wcout << e.what() << endl;
}
return 0;
}
是的,您可以根据 URI 设置多个 http_listeners。效果很好。