Commit 1079584e authored by yangjian's avatar yangjian
Browse files

add udr

parent 6b080b4a
# REST API Server for Nudr_DataRepository API OpenAPI file
## Overview
This API Server was generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
It uses the [Pistache](https://github.com/oktal/pistache) Framework.
## Files organization
The Pistache C++ REST server generator creates three folders:
- `api`: This folder contains the handlers for each method specified in the OpenAPI definition. Every handler extracts
the path and body parameters (if any) from the requests and tries to parse and possibly validate them.
Once this step is completed, the main API class calls the corresponding abstract method that should be implemented
by the developer (a basic implementation is provided under the `impl` folder)
- `impl`: As written above, the implementation folder contains, for each API, the corresponding implementation class,
which extends the main API class and implements the abstract methods.
Every method receives the path and body parameters as constant reference variables and a reference to the response
object, that should be filled with the right response and sent at the end of the method with the command:
response.send(returnCode, responseBody, [mimeType])
- `model`: This folder contains the corresponding class for every object schema found in the OpenAPI specification.
The main folder contains also a file with a main that can be used to start the server.
Of course, is you should customize this file based on your needs
## Installation
First of all, you need to download and install the libraries listed [here](#libraries-required).
Once the libraries are installed, in order to compile and run the server please follow the steps below:
```bash
cd scripts
./build_udr
```
Once compiled run the server:
```bash
cd build
./udr
```
## Libraries required
- [pistache](http://pistache.io/quickstart): Please download the `Pistache` project and
put the "include" folder and the generated "*.so" file into external/include/ and external/lib/ after compilation
- [JSON for Modern C++](https://github.com/nlohmann/json/#integration): Please download the `json.hpp` file and
put it under the external/include/nlohmann folder
## Namespaces
org.openapitools.server.api
org.openapitools.server.model
This diff is collapsed.
This diff is collapsed.
/*
Copyright (C) 2019-2020, Kip Warner.
Released under the terms of Apache License 2.0.
*/
// Multiple include protection...
#ifndef _BASE_64_H_
#define _BASE_64_H_
// Includes...
// Build environment configuration...
#include <pistache/config.h>
// Standard C++ / POSIX system headers...
#include <cstddef>
#include <string>
#include <vector>
#if __cplusplus < 201703L
namespace std {
typedef uint8_t byte;
}
#endif
// A class for performing decoding to raw bytes from base 64 encoding...
class Base64Decoder {
// Public methods...
public:
// Constructor...
explicit Base64Decoder(const std::string &Base64EncodedString)
: m_Base64EncodedString(Base64EncodedString) {}
// Calculate length of decoded raw bytes from that would be generated if
// the base 64 encoded input buffer was decoded. This is not a static
// method because we need to examine the string...
std::vector<std::byte>::size_type CalculateDecodedSize() const;
// Decode base 64 encoding into raw bytes...
const std::vector<std::byte> &Decode();
// Get raw decoded data...
const std::vector<std::byte> &GetRawDecodedData() const noexcept {
return m_DecodedData;
}
// Protected methods...
protected:
// Convert an octet character to corresponding sextet, provided it can
// safely be represented as such. Otherwise return 0xff...
std::byte DecodeCharacter(const unsigned char Character) const;
// Protected attributes...
protected:
// Base 64 encoded string to decode...
const std::string &m_Base64EncodedString;
// Decoded raw data...
std::vector<std::byte> m_DecodedData;
};
// A class for performing base 64 encoding from raw bytes...
class Base64Encoder {
// Public methods...
public:
// Construct encoder to encode from a raw input buffer...
explicit Base64Encoder(const std::vector<std::byte> &InputBuffer)
: m_InputBuffer(InputBuffer) {}
// Calculate length of base 64 string that would need to be generated
// for raw data of a given length...
static std::string::size_type CalculateEncodedSize(
const std::vector<std::byte>::size_type DecodedSize) noexcept;
// Encode raw data input buffer to base 64...
const std::string &Encode() noexcept;
// Encode a string into base 64 format...
static std::string EncodeString(const std::string &StringInput);
// Get the encoded data...
const std::string &GetBase64EncodedString() const noexcept {
return m_Base64EncodedString;
}
// Protected methods...
protected:
// Encode single binary byte to 6-bit base 64 character...
unsigned char EncodeByte(const std::byte Byte) const;
// Protected attributes...
protected:
// Raw bytes to encode to base 64 string...
const std::vector<std::byte> &m_InputBuffer;
// Base64 encoded string...
std::string m_Base64EncodedString;
};
// Multiple include protection...
#endif
/*
Mathieu Stefani, 29 janvier 2016
The Http client
*/
#pragma once
#include <pistache/async.h>
#include <pistache/http.h>
#include <pistache/os.h>
#include <pistache/reactor.h>
#include <pistache/timer_pool.h>
#include <pistache/view.h>
#include <atomic>
#include <chrono>
#include <functional>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
namespace Pistache {
namespace Http {
namespace Default {
constexpr int Threads = 1;
constexpr int MaxConnectionsPerHost = 8;
constexpr bool KeepAlive = true;
constexpr size_t MaxResponseSize = std::numeric_limits<uint32_t>::max();
} // namespace Default
class Transport;
struct Connection : public std::enable_shared_from_this<Connection> {
using OnDone = std::function<void()>;
explicit Connection(size_t maxResponseSize);
struct RequestData {
RequestData(Async::Resolver resolve, Async::Rejection reject,
const Http::Request &request, OnDone onDone)
: resolve(std::move(resolve)), reject(std::move(reject)),
request(request), onDone(std::move(onDone)) {}
Async::Resolver resolve;
Async::Rejection reject;
Http::Request request;
OnDone onDone;
};
enum State : uint32_t { Idle, Used };
enum ConnectionState { NotConnected, Connecting, Connected };
void connect(const Address &addr);
void close();
bool isIdle() const;
bool tryUse();
void setAsIdle();
bool isConnected() const;
bool hasTransport() const;
void associateTransport(const std::shared_ptr<Transport> &transport);
Async::Promise<Response> perform(const Http::Request &request, OnDone onDone);
Async::Promise<Response> asyncPerform(const Http::Request &request,
OnDone onDone);
void performImpl(const Http::Request &request, Async::Resolver resolve,
Async::Rejection reject, OnDone onDone);
Fd fd() const;
void handleResponsePacket(const char *buffer, size_t totalBytes);
void handleError(const char *error);
void handleTimeout();
std::string dump() const;
private:
void processRequestQueue();
struct RequestEntry {
RequestEntry(Async::Resolver resolve, Async::Rejection reject,
std::shared_ptr<TimerPool::Entry> timer, OnDone onDone)
: resolve(std::move(resolve)), reject(std::move(reject)),
timer(std::move(timer)), onDone(std::move(onDone)) {}
Async::Resolver resolve;
Async::Rejection reject;
std::shared_ptr<TimerPool::Entry> timer;
OnDone onDone;
};
Fd fd_;
struct sockaddr_in saddr;
std::unique_ptr<RequestEntry> requestEntry;
std::atomic<uint32_t> state_;
std::atomic<ConnectionState> connectionState_;
std::shared_ptr<Transport> transport_;
Queue<RequestData> requestsQueue;
TimerPool timerPool_;
ResponseParser parser;
};
class ConnectionPool {
public:
ConnectionPool() = default;
void init(size_t maxConnsPerHost, size_t maxResponseSize);
std::shared_ptr<Connection> pickConnection(const std::string &domain);
static void releaseConnection(const std::shared_ptr<Connection> &connection);
size_t usedConnections(const std::string &domain) const;
size_t idleConnections(const std::string &domain) const;
size_t availableConnections(const std::string &domain) const;
void closeIdleConnections(const std::string &domain);
void shutdown();
private:
using Connections = std::vector<std::shared_ptr<Connection>>;
using Lock = std::mutex;
using Guard = std::lock_guard<Lock>;
mutable Lock connsLock;
std::unordered_map<std::string, Connections> conns;
size_t maxConnectionsPerHost;
size_t maxResponseSize;
};
class Client;
class RequestBuilder {
public:
friend class Client;
RequestBuilder &method(Method method);
RequestBuilder &resource(const std::string &val);
RequestBuilder &params(const Uri::Query &query);
RequestBuilder &header(const std::shared_ptr<Header::Header> &header);
template <typename H, typename... Args>
typename std::enable_if<Header::IsHeader<H>::value, RequestBuilder &>::type
header(Args &&... args) {
return header(std::make_shared<H>(std::forward<Args>(args)...));
}
RequestBuilder &cookie(const Cookie &cookie);
RequestBuilder &body(const std::string &val);
RequestBuilder &body(std::string &&val);
RequestBuilder &timeout(std::chrono::milliseconds val);
Async::Promise<Response> send();
private:
explicit RequestBuilder(Client *const client) : client_(client), request_() {}
Client *const client_;
Request request_;
};
class Client {
public:
friend class RequestBuilder;
struct Options {
friend class Client;
Options()
: threads_(Default::Threads),
maxConnectionsPerHost_(Default::MaxConnectionsPerHost),
keepAlive_(Default::KeepAlive),
maxResponseSize_(Default::MaxResponseSize) {}
Options &threads(int val);
Options &keepAlive(bool val);
Options &maxConnectionsPerHost(int val);
Options &maxResponseSize(size_t val);
private:
int threads_;
int maxConnectionsPerHost_;
bool keepAlive_;
size_t maxResponseSize_;
};
Client();
~Client();
static Options options();
void init(const Options &options = Options());
RequestBuilder get(const std::string &resource);
RequestBuilder post(const std::string &resource);
RequestBuilder put(const std::string &resource);
RequestBuilder patch(const std::string &resource);
RequestBuilder del(const std::string &resource);
void shutdown();
private:
std::shared_ptr<Aio::Reactor> reactor_;
ConnectionPool pool;
Aio::Reactor::Key transportKey;
std::atomic<uint64_t> ioIndex;
using Lock = std::mutex;
using Guard = std::lock_guard<Lock>;
Lock queuesLock;
std::unordered_map<std::string,
MPMCQueue<std::shared_ptr<Connection::RequestData>, 2048>>
requestsQueues;
bool stopProcessPequestsQueues;
private:
RequestBuilder prepareRequest(const std::string &resource,
Http::Method method);
Async::Promise<Response> doRequest(Http::Request request);
void processRequestQueue();
};
} // namespace Http
} // namespace Pistache
/* common.h
Mathieu Stefani, 12 August 2015
A collection of macro / utilities / constants
*/
#pragma once
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <cstring>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#define TRY(...) \
do { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": "; \
if (errno == 0) { \
oss << gai_strerror(static_cast<int>(ret)); \
} else { \
oss << strerror(errno); \
} \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
} while (0)
#define TRY_RET(...) \
[&]() { \
auto ret = __VA_ARGS__; \
if (ret < 0) { \
const char *str = #__VA_ARGS__; \
std::ostringstream oss; \
oss << str << ": " << strerror(errno); \
oss << " (" << __FILE__ << ":" << __LINE__ << ")"; \
throw std::runtime_error(oss.str()); \
} \
return ret; \
}(); \
(void)0
struct PrintException {
void operator()(std::exception_ptr exc) const {
try {
std::rethrow_exception(exc);
} catch (const std::exception &e) {
std::cerr << "An exception occured: " << e.what() << std::endl;
}
}
};
#define unreachable() __builtin_unreachable()
// Until we require C++17 compiler with [[maybe_unused]]
#define UNUSED(x) (void)(x);
#pragma once
#include <cstddef>
#include <cstdint>
#include <limits>
// Allow compile-time overload
namespace Pistache {
namespace Const {
static constexpr size_t MaxBacklog = 128;
static constexpr size_t MaxEvents = 1024;
static constexpr size_t MaxBuffer = 4096;
static constexpr size_t DefaultWorkers = 1;
static constexpr size_t DefaultTimerPoolSize = 128;
// Defined from CMakeLists.txt in project root
static constexpr size_t DefaultMaxRequestSize = 4096;
static constexpr size_t DefaultMaxResponseSize =
std::numeric_limits<uint32_t>::max();
static constexpr size_t ChunkSize = 1024;
static constexpr uint16_t HTTP_STANDARD_PORT = 80;
} // namespace Const
} // namespace Pistache
/*
Mathieu Stefani, 16 janvier 2016
Representation of a Cookie as per http://tools.ietf.org/html/rfc6265
*/
#pragma once
#include <ctime>
#include <list>
#include <map>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <pistache/http_defs.h>
#include <pistache/optional.h>
namespace Pistache {
namespace Http {
struct Cookie {
friend std::ostream &operator<<(std::ostream &os, const Cookie &cookie);
Cookie(std::string name, std::string value);
std::string name;
std::string value;
Optional<std::string> path;
Optional<std::string> domain;
Optional<FullDate> expires;
Optional<int> maxAge;
bool secure;
bool httpOnly;
std::map<std::string, std::string> ext;
static Cookie fromRaw(const char *str, size_t len);
static Cookie fromString(const std::string &str);
private:
void write(std::ostream &os) const;
};
std::ostream &operator<<(std::ostream &os, const Cookie &cookie);
class CookieJar {
public:
using HashMapCookies =
std::unordered_map<std::string, Cookie>; // "value" -> Cookie
using Storage = std::unordered_map<
std::string, HashMapCookies>; // "name" -> Hashmap("value" -> Cookie)
struct iterator : std::iterator<std::bidirectional_iterator_tag, Cookie> {
explicit iterator(const Storage::const_iterator &_iterator)
: iter_storage(_iterator), iter_cookie_values(), iter_storage_end() {}
iterator(const Storage::const_iterator &_iterator,
const Storage::const_iterator &end)
: iter_storage(_iterator), iter_cookie_values(), iter_storage_end(end) {
if (iter_storage != iter_storage_end) {
iter_cookie_values = iter_storage->second.begin();
}
}
Cookie operator*() const {
return iter_cookie_values->second; // return iter_storage->second;
}
const Cookie *operator->() const { return &(iter_cookie_values->second); }
iterator &operator++() {
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if (iter_storage != iter_storage_end)
iter_cookie_values = iter_storage->second.begin();
}
return *this;
}
iterator operator++(int) {
iterator ret(iter_storage, iter_storage_end);
++iter_cookie_values;
if (iter_cookie_values == iter_storage->second.end()) {
++iter_storage;
if (iter_storage != iter_storage_end) // this check is important
iter_cookie_values = iter_storage->second.begin();
}
return ret;
}
bool operator!=(iterator other) const {
return iter_storage != other.iter_storage;
}
bool operator==(iterator other) const {
return iter_storage == other.iter_storage;
}
private:
Storage::const_iterator iter_storage;
HashMapCookies::const_iterator iter_cookie_values;
Storage::const_iterator
iter_storage_end; // we need to know where main hashmap ends.
};
CookieJar();
void add(const Cookie &cookie);
void removeAllCookies();
void addFromRaw(const char *str, size_t len);
Cookie get(const std::string &name) const;
bool has(const std::string &name) const;
iterator begin() const { return iterator(cookies.begin(), cookies.end()); }
iterator end() const { return iterator(cookies.end()); }
private:
Storage cookies;
};