Commit 76db321d authored by octal's avatar octal

Removed rapidjson dependency

parent 7c5ac289
[submodule "thirdparty/rapidjson"]
path = thirdparty/rapidjson
url = https://github.com/miloyip/rapidjson.git
......@@ -16,9 +16,6 @@ include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include)
file(GLOB HEADER_FILES "include/*.h")
install(FILES ${HEADER_FILES} DESTINATION include/pistache)
add_subdirectory (thirdparty)
include_directories(${RapidJSON_SOURCE_DIR}/include)
add_subdirectory (src)
include_directories (src)
......
......@@ -13,5 +13,9 @@ target_link_libraries(custom_header net)
add_executable(rest_server rest_server.cc)
target_link_libraries(rest_server net)
find_package(RapidJSON)
if (RapidJSON_FOUND)
include_directories(${RapidJSON_INCLUDE_DIRS})
add_executable(rest_description rest_description.cc)
target_link_libraries(rest_description net)
endif()
......@@ -7,6 +7,7 @@
#include "http.h"
#include "description.h"
#include "endpoint.h"
#include "serializer/rapidjson.h"
using namespace std;
using namespace Net;
......@@ -42,6 +43,7 @@ public:
.uiPath("/doc")
.uiDirectory("/home/octal/code/web/swagger-ui-2.1.4/dist")
.apiPath("/banker-api.json")
.serializer(&Rest::Serializer::rapidJson)
.install(router);
httpEndpoint->setHandler(router.handler());
......
......@@ -107,26 +107,6 @@ struct ProduceConsume {
std::vector<Http::Mime::MediaType> produce;
std::vector<Http::Mime::MediaType> consume;
template<typename Writer>
void serialize(Writer& writer) const {
auto serializeMimes = [&](const char* name, const std::vector<Http::Mime::MediaType>& mimes) {
if (!mimes.empty()) {
writer.String(name);
writer.StartArray();
{
for (const auto& mime: mimes) {
auto str = mime.toString();
writer.String(str.c_str());
}
}
writer.EndArray();
}
};
serializeMimes("consumes", consume);
serializeMimes("produces", produce);
}
};
struct Contact {
......@@ -154,29 +134,6 @@ struct Info {
Optional<Contact> contact;
Optional<License> license;
template<typename Writer>
void serialize(Writer& writer) const {
writer.String("swagger");
writer.String("2.0");
writer.String("info");
writer.StartObject();
{
writer.String("title");
writer.String(title.c_str());
writer.String("version");
writer.String(version.c_str());
if (!description.empty()) {
writer.String("description");
writer.String(description.c_str());
}
if (!termsOfService.empty()) {
writer.String("termsOfService");
writer.String(termsOfService.c_str());
}
}
writer.EndObject();
}
};
struct InfoBuilder {
......@@ -223,25 +180,6 @@ struct Parameter {
return p;
}
template<typename Writer>
void serialize(Writer& writer) const {
writer.StartObject();
{
writer.String("name");
writer.String(name.c_str());
writer.String("in");
// @Feature: support other types of parameters
writer.String("path");
writer.String("description");
writer.String(description.c_str());
writer.String("required");
writer.Bool(required);
writer.String("type");
writer.String(type->typeName());
}
writer.EndObject();
}
std::string name;
std::string description;
bool required;
......@@ -254,18 +192,6 @@ struct Response {
Http::Code statusCode;
std::string description;
template<typename Writer>
void serialize(Writer& writer) const {
auto code = std::to_string(static_cast<uint32_t>(statusCode));
writer.String(code.c_str());
writer.StartObject();
{
writer.String("description");
writer.String(description.c_str());
}
writer.EndObject();
}
};
struct ResponseBuilder {
......@@ -303,43 +229,6 @@ struct Path {
bool isBound() const {
return handler != nullptr;
}
template<typename Writer>
void serialize(Writer& writer) const {
std::string methodStr(methodString(method));
// So it looks like Swagger requires method to be in lowercase
std::transform(std::begin(methodStr), std::end(methodStr), std::begin(methodStr), ::tolower);
writer.String(methodStr.c_str());
writer.StartObject();
{
writer.String("description");
writer.String(description.c_str());
pc.serialize(writer);
if (!parameters.empty()) {
writer.String("parameters");
writer.StartArray();
{
for (const auto& parameter: parameters) {
parameter.serialize(writer);
}
}
writer.EndArray();
}
if (!responses.empty()) {
writer.String("responses");
writer.StartObject();
{
for (const auto& response: responses) {
response.serialize(writer);
}
}
writer.EndObject();
}
}
writer.EndObject();
}
};
class PathGroup {
......@@ -383,43 +272,10 @@ public:
flat_iterator flatBegin() const;
flat_iterator flatEnd() const;
template<typename Writer>
void serialize(
Writer& writer, const std::string& prefix, Format format = Format::Default) const {
writer.String("paths");
writer.StartObject();
{
for (const auto& group: groups) {
if (group.second.isHidden()) continue;
std::string name(group.first);
if (!prefix.empty()) {
if (!name.compare(0, prefix.size(), prefix)) {
name = name.substr(prefix.size());
}
}
if (format == Format::Default) {
writer.String(name.c_str());
} else {
auto swaggerPath = Path::swaggerFormat(name);
writer.String(swaggerPath.c_str());
}
writer.StartObject();
{
for (const auto& path: group.second) {
if (!path.hidden)
path.serialize(writer);
}
}
writer.EndObject();
}
}
writer.EndObject();
}
Map groups() const { return groups_; }
private:
Map groups;
Map groups_;
};
struct PathBuilder {
......@@ -555,37 +411,12 @@ public:
Schema::ResponseBuilder response(Http::Code statusCode, std::string description);
Schema::PathGroup paths() const { return paths_; }
template<typename Writer>
void serialize(Writer& writer) const {
writer.StartObject();
{
info_.serialize(writer);
if (!host_.empty()) {
writer.String("host");
writer.String(host_.c_str());
}
if (!basePath_.empty()) {
writer.String("basePath");
writer.String(basePath_.c_str());
}
if (!schemes_.empty()) {
writer.String("schemes");
writer.StartArray();
{
for (const auto& scheme: schemes_) {
writer.String(schemeString(scheme));
}
}
writer.EndArray();
}
pc.serialize(writer);
paths_.serialize(writer, basePath_, Schema::PathGroup::Format::Swagger);
}
writer.EndObject();
}
Schema::Info rawInfo() const { return info_; }
std::string rawHost() const { return host_; }
std::string rawBasePath() const { return basePath_; }
std::vector<Scheme> rawSchemes() const { return schemes_; }
Schema::ProduceConsume rawPC() const { return pc; }
Schema::PathGroup rawPaths() const { return paths_; }
private:
Schema::Info info_;
......@@ -603,9 +434,12 @@ public:
: description_(description)
{ }
typedef std::function<std::string (const Description&)> Serializer;
Swagger& uiPath(std::string path);
Swagger& uiDirectory(std::string dir);
Swagger& apiPath(std::string path);
Swagger& serializer(Serializer serialize);
void install(Rest::Router& router);
......@@ -614,6 +448,7 @@ private:
std::string uiPath_;
std::string uiDirectory_;
std::string apiPath_;
Serializer serializer_;
};
} // namespace Rest
......
/*
Mathieu Stefani, 14 mai 2016
Swagger serializer for RapidJSON
*/
#pragma once
#include "description.h"
#include <rapidjson/prettywriter.h>
#include "http_defs.h"
#include "mime.h"
namespace Net {
namespace Rest {
namespace Serializer {
template<typename Writer>
void serializeInfo(Writer& writer, const Schema::Info& info) {
writer.String("swagger");
writer.String("2.0");
writer.String("info");
writer.StartObject();
{
writer.String("title");
writer.String(info.title.c_str());
writer.String("version");
writer.String(info.version.c_str());
if (!info.description.empty()) {
writer.String("description");
writer.String(info.description.c_str());
}
if (!info.termsOfService.empty()) {
writer.String("termsOfService");
writer.String(info.termsOfService.c_str());
}
}
writer.EndObject();
}
template<typename Writer>
void serializePC(Writer& writer, const Schema::ProduceConsume& pc) {
auto serializeMimes = [&](const char* name, const std::vector<Http::Mime::MediaType>& mimes) {
if (!mimes.empty()) {
writer.String(name);
writer.StartArray();
{
for (const auto& mime: mimes) {
auto str = mime.toString();
writer.String(str.c_str());
}
}
writer.EndArray();
}
};
serializeMimes("consumes", pc.consume);
serializeMimes("produces", pc.produce);
}
template<typename Writer>
void serializeParameter(Writer& writer, const Schema::Parameter& parameter) {
writer.StartObject();
{
writer.String("name");
writer.String(parameter.name.c_str());
writer.String("in");
// @Feature: support other types of parameters
writer.String("path");
writer.String("description");
writer.String(parameter.description.c_str());
writer.String("required");
writer.Bool(parameter.required);
writer.String("type");
writer.String(parameter.type->typeName());
}
writer.EndObject();
}
template<typename Writer>
void serializeResponse(Writer& writer, const Schema::Response& response) {
auto code = std::to_string(static_cast<uint32_t>(response.statusCode));
writer.String(code.c_str());
writer.StartObject();
{
writer.String("description");
writer.String(response.description.c_str());
}
writer.EndObject();
}
template<typename Writer>
void serializePath(Writer& writer, const Schema::Path& path) {
std::string methodStr(methodString(path.method));
// So it looks like Swagger requires method to be in lowercase
std::transform(std::begin(methodStr), std::end(methodStr), std::begin(methodStr), ::tolower);
writer.String(methodStr.c_str());
writer.StartObject();
{
writer.String("description");
writer.String(path.description.c_str());
serializePC(writer, path.pc);
const auto& parameters = path.parameters;
if (!parameters.empty()) {
writer.String("parameters");
writer.StartArray();
{
for (const auto& parameter: parameters) {
serializeParameter(writer, parameter);
}
}
writer.EndArray();
}
const auto& responses = path.responses;
if (!responses.empty()) {
writer.String("responses");
writer.StartObject();
{
for (const auto& response: responses) {
serializeResponse(writer, response);
}
}
writer.EndObject();
}
}
writer.EndObject();
}
template<typename Writer>
void serializePathGroups(
Writer& writer, const std::string& prefix,
const Schema::PathGroup& paths, Schema::PathGroup::Format format) {
writer.String("paths");
writer.StartObject();
{
auto groups = paths.groups();
for (const auto& group: groups) {
if (group.second.isHidden()) continue;
std::string name(group.first);
if (!prefix.empty()) {
if (!name.compare(0, prefix.size(), prefix)) {
name = name.substr(prefix.size());
}
}
if (format == Schema::PathGroup::Format::Default) {
writer.String(name.c_str());
} else {
auto swaggerPath = Schema::Path::swaggerFormat(name);
writer.String(swaggerPath.c_str());
}
writer.StartObject();
{
for (const auto& path: group.second) {
if (!path.hidden)
serializePath(writer, path);
}
}
writer.EndObject();
}
}
writer.EndObject();
}
template<typename Writer>
void serializeDescription(Writer& writer, const Description& desc) {
writer.StartObject();
{
serializeInfo(writer, desc.rawInfo());
auto host = desc.rawHost();
auto basePath = desc.rawBasePath();
auto schemes = desc.rawSchemes();
auto pc = desc.rawPC();
auto paths = desc.rawPaths();
if (!host.empty()) {
writer.String("host");
writer.String(host.c_str());
}
if (!basePath.empty()) {
writer.String("basePath");
writer.String(basePath.c_str());
}
if (!schemes.empty()) {
writer.String("schemes");
writer.StartArray();
{
for (const auto& scheme: schemes) {
writer.String(schemeString(scheme));
}
}
writer.EndArray();
}
serializePC(writer, pc);
serializePathGroups(writer, basePath, paths, Schema::PathGroup::Format::Swagger);
}
writer.EndObject();
}
std::string rapidJson(const Description& desc) {
rapidjson::StringBuffer sb;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
serializeDescription(writer, desc);
return sb.GetString();
}
} // namespace Serializer
} // namespace Rest
} // namespace Net
......@@ -8,7 +8,6 @@
#include "http_header.h"
#include <sstream>
#include <algorithm>
#include "rapidjson/prettywriter.h"
namespace Net {
......@@ -136,8 +135,8 @@ PathGroup::hasPath(const Path& path) const {
PathGroup::Group
PathGroup::paths(const std::string& name) const {
auto it = groups.find(name);
if (it == std::end(groups))
auto it = groups_.find(name);
if (it == std::end(groups_))
return PathGroup::Group { };
return it->second;
......@@ -161,28 +160,28 @@ PathGroup::add(Path path) {
if (hasPath(path))
return PathGroup::group_iterator { };
auto &group = groups[path.value];
auto &group = groups_[path.value];
return group.insert(group.end(), std::move(path));
}
PathGroup::const_iterator
PathGroup::begin() const {
return groups.begin();
return groups_.begin();
}
PathGroup::const_iterator
PathGroup::end() const {
return groups.end();
return groups_.end();
}
PathGroup::flat_iterator
PathGroup::flatBegin() const {
return makeFlatMapIterator(groups, begin());
return makeFlatMapIterator(groups_, begin());
}
PathGroup::flat_iterator
PathGroup::flatEnd() const {
return makeFlatMapIterator(groups, end());
return makeFlatMapIterator(groups_, end());
}
PathBuilder::PathBuilder(Path* path)
......@@ -342,6 +341,12 @@ Swagger::apiPath(std::string path) {
return *this;
}
Swagger&
Swagger::serializer(Swagger::Serializer serialize) {
serializer_ = std::move(serialize);
return *this;
}
void
Swagger::install(Rest::Router& router) {
......@@ -430,12 +435,7 @@ Swagger::install(Rest::Router& router) {
}
else if (res == apiPath_) {
rapidjson::StringBuffer sb;
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(sb);
description_.serialize(writer);
response.send(Http::Code::Ok, sb.GetString(), MIME(Application, Json));
response.send(Http::Code::Ok, serializer_(description_), MIME(Application, Json));
return Route::Result::Ok;
}
......
......@@ -244,7 +244,7 @@ Router::handler() const {
void
Router::initFromDescription(const Rest::Description& desc) {
auto paths = desc.paths();
auto paths = desc.rawPaths();
for (auto it = paths.flatBegin(), end = paths.flatEnd(); it != end; ++it) {
const auto& paths = *it;
for (const auto& path: paths) {
......
add_subdirectory(rapidjson)
Subproject commit c02d52ad56595dc70b38daf46b5f315d3a7115fa
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment