ZRColaWS: Rearrange source and provide Swagger-UI documentation
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
09117d68a6
commit
004958f464
@ -61,10 +61,10 @@ The `/ls` flag can be appended to the commands above to reduce NMAKE's verbosity
|
||||
### Building Environment Requirements
|
||||
- Linux
|
||||
- _gcc_, _make_
|
||||
- [oat++ 1.3.0](https://oatpp.io/)
|
||||
- [Oat++ 1.3.0](https://oatpp.io/)
|
||||
|
||||
### oat++
|
||||
ZRCola webservice is using oat++ library. You have to compile the library and install it to `/usr/local`.
|
||||
### Oat++
|
||||
ZRCola webservice is using Oat++ library. You have to compile the oatpp and oatpp-swagger libraries and install them to `/usr/local`.
|
||||
|
||||
### Building
|
||||
Use `make -C ZRColaWS all` to build the project.
|
||||
|
@ -1,6 +1,6 @@
|
||||
CPPFLAGS := $(CPPFLAGS) -I../lib/libZRCola/include -I../lib/stdex/include -I/usr/local/include/oatpp-1.3.0/oatpp
|
||||
CPPFLAGS := $(CPPFLAGS) -I../lib/libZRCola/include -I../lib/stdex/include -I/usr/local/include/oatpp-1.3.0/oatpp -I/usr/local/include/oatpp-1.3.0/oatpp-swagger
|
||||
LDFLAGS := $(LDFLAGS) -L../lib/libZRCola/lib -L/usr/local/lib64/oatpp-1.3.0
|
||||
LDLIBS := $(LDLIBS) -lZRCola -loatpp -lstdc++
|
||||
LDLIBS := $(LDLIBS) -lZRCola -loatpp-swagger -loatpp -lstdc++
|
||||
SRCS := zrcolaws.cpp
|
||||
|
||||
include ../include/props.mak
|
||||
|
@ -5,7 +5,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../include/version.h"
|
||||
#include "controller.hpp"
|
||||
#include <oatpp-swagger/Model.hpp>
|
||||
#include <oatpp-swagger/Resources.hpp>
|
||||
#include <oatpp/core/base/CommandLineArguments.hpp>
|
||||
#include <oatpp/core/macro/component.hpp>
|
||||
#include <oatpp/network/Server.hpp>
|
||||
@ -16,20 +19,13 @@
|
||||
class AppComponent
|
||||
{
|
||||
protected:
|
||||
const oatpp::base::CommandLineArguments& m_cmdArgs;
|
||||
oatpp::network::Address m_address;
|
||||
|
||||
public:
|
||||
AppComponent(const oatpp::base::CommandLineArguments& cmdArgs) : m_cmdArgs(cmdArgs) {}
|
||||
AppComponent(const oatpp::network::Address& address) : m_address(address) {}
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, serverConnectionProvider)([this] {
|
||||
oatpp::String host = m_cmdArgs.getNamedArgumentValue("--host", "localhost");
|
||||
v_uint16 port = oatpp::utils::conversion::strToInt32(m_cmdArgs.getNamedArgumentValue("--port", "8000"));
|
||||
oatpp::network::Address::Family family = oatpp::network::Address::UNSPEC;
|
||||
if (m_cmdArgs.hasArgument("-4"))
|
||||
family = oatpp::network::Address::IP_4;
|
||||
else if (m_cmdArgs.hasArgument("-6"))
|
||||
family = oatpp::network::Address::IP_6;
|
||||
return oatpp::network::tcp::server::ConnectionProvider::createShared({host, port, family});
|
||||
return oatpp::network::tcp::server::ConnectionProvider::createShared({m_address.host, m_address.port, m_address.family});
|
||||
}());
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, httpRouter)([] {
|
||||
@ -45,14 +41,31 @@ public:
|
||||
return oatpp::parser::json::mapping::ObjectMapper::createShared();
|
||||
}());
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<Controller>, controller)([] {
|
||||
OATPP_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper);
|
||||
return std::make_shared<Controller>(objectMapper);
|
||||
}());
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::network::Server>, server)([] {
|
||||
OATPP_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, connectionProvider);
|
||||
OATPP_COMPONENT(std::shared_ptr<oatpp::network::ConnectionHandler>, connectionHandler);
|
||||
return oatpp::network::Server::createShared(connectionProvider, connectionHandler);
|
||||
}());
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::swagger::DocumentInfo>, swaggerDocumentInfo)([this] {
|
||||
oatpp::swagger::DocumentInfo::Builder builder;
|
||||
builder
|
||||
.setTitle("ZRCola Web Service")
|
||||
.setDescription(
|
||||
"ZRCola is an input system designed mainly, although not exclusively, for linguistic use. "
|
||||
"It allows the user to combine basic letters with any diacritic marks and insert the resulting complex characters into the texts with ease.")
|
||||
.setVersion(PRODUCT_VERSION_STR)
|
||||
.setContactName("ZRCola")
|
||||
.setContactUrl("https://zrcola.zrc-sazu.si/en/")
|
||||
|
||||
.setLicenseName("GNU General Public License, Version 3")
|
||||
.setLicenseUrl("https://www.gnu.org/licenses/gpl-3.0.en.html")
|
||||
|
||||
.addServer(oatpp::String("http://") + m_address.host + ":" + std::to_string(m_address.port), "API Server");
|
||||
return builder.build();
|
||||
}());
|
||||
|
||||
OATPP_CREATE_COMPONENT(std::shared_ptr<oatpp::swagger::Resources>, swaggerResources)([] {
|
||||
return oatpp::swagger::Resources::loadResources(PREFIX "/include/oatpp-1.3.0/bin/oatpp-swagger/res");
|
||||
}());
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../include/version.h"
|
||||
#include "dto.hpp"
|
||||
#include "iconverter.hpp"
|
||||
#include "zrcolaws.hpp"
|
||||
@ -23,31 +24,44 @@ public:
|
||||
{}
|
||||
|
||||
ADD_CORS(getAbout)
|
||||
ENDPOINT_INFO(getAbout) {
|
||||
info->summary = "Returns service information";
|
||||
info->addResponse<Object<dto::About>>(Status::CODE_200, "application/json");
|
||||
}
|
||||
ENDPOINT("GET", "/about", getAbout)
|
||||
{
|
||||
return createDtoResponse(Status::CODE_200, aboutDto::createShared());
|
||||
auto dto = dto::About::createShared();
|
||||
dto->vendor = PRODUCT_CFG_VENDOR;
|
||||
dto->application = PRODUCT_CFG_APPLICATION;
|
||||
dto->version = PRODUCT_VERSION_STR;
|
||||
return createDtoResponse(Status::CODE_200, dto);
|
||||
}
|
||||
|
||||
ADD_CORS(getTranset)
|
||||
ENDPOINT_INFO(getTranset) {
|
||||
info->summary = "Lists supported translation sets";
|
||||
info->description = "Each translation set describes a set of replacements that are performed to translate text from one script or encoding to another. ";
|
||||
info->addResponse<oatpp::Vector<oatpp::Object<dto::TranSet>>>(Status::CODE_200, "application/json");
|
||||
}
|
||||
ENDPOINT("GET", "/transet", getTranset)
|
||||
{
|
||||
try {
|
||||
utf16toutf8 c;
|
||||
auto result = oatpp::Vector<oatpp::Object<transetDto>>::createShared();
|
||||
auto dto = transetDto::createShared();
|
||||
auto result = oatpp::Vector<oatpp::Object<dto::TranSet>>::createShared();
|
||||
auto dto = dto::TranSet::createShared();
|
||||
dto->set = ZRCOLA_TRANSETID_DEFAULT;
|
||||
dto->src = "ZRCola Decomposed";
|
||||
dto->dst = "ZRCola Composed";
|
||||
result->push_back(dto);
|
||||
for (size_t i = 0, n = ts_db.idxTranSet.size(); i < n; i++) {
|
||||
const auto &ts = ts_db.idxTranSet[i];
|
||||
dto = transetDto::createShared();
|
||||
dto = dto::TranSet::createShared();
|
||||
dto->set = ts.set;
|
||||
dto->src = c.convert(ts.src(), ts.src_len());
|
||||
dto->dst = c.convert(ts.dst(), ts.dst_len());
|
||||
result->push_back(dto);
|
||||
}
|
||||
dto = transetDto::createShared();
|
||||
dto = dto::TranSet::createShared();
|
||||
dto->set = ZRCOLA_TRANSETID_UNICODE;
|
||||
dto->src = "ZRCola Decomposed";
|
||||
dto->dst = "Unicode";
|
||||
@ -60,14 +74,19 @@ public:
|
||||
}
|
||||
|
||||
ADD_CORS(getLanguage)
|
||||
ENDPOINT_INFO(getLanguage) {
|
||||
info->summary = "Lists supported languages";
|
||||
info->description = "Each language describes a set of special characters that are specific to that language (e.g. č, š, ž in Slovenian, or ä, ö, ü in German).";
|
||||
info->addResponse<oatpp::Vector<oatpp::Object<dto::Language>>>(Status::CODE_200, "application/json");
|
||||
}
|
||||
ENDPOINT("GET", "/language", getLanguage)
|
||||
{
|
||||
try {
|
||||
utf16toutf8 c;
|
||||
auto result = oatpp::Vector<oatpp::Object<languageDto>>::createShared();
|
||||
auto result = oatpp::Vector<oatpp::Object<dto::Language>>::createShared();
|
||||
for (size_t i = 0, n = lang_db.idxLang.size(); i < n; i++) {
|
||||
const auto &lang = lang_db.idxLang[i];
|
||||
auto dto = languageDto::createShared();
|
||||
auto dto = dto::Language::createShared();
|
||||
dto->lang = std::string(&lang.lang.data[0], strnlen(lang.lang.data, std::size(lang.lang.data)));
|
||||
dto->name = c.convert(lang.name(), lang.name_len());
|
||||
result->push_back(dto);
|
||||
@ -80,7 +99,21 @@ public:
|
||||
}
|
||||
|
||||
ADD_CORS(postTranslate)
|
||||
ENDPOINT("POST", "/translate", postTranslate, BODY_DTO(Object<translateInDto>, input))
|
||||
ENDPOINT_INFO(postTranslate) {
|
||||
info->summary = "Translate text";
|
||||
info->description =
|
||||
"Performs any number of supported translations (see /transet) on a given input text in a sequence. "
|
||||
"Together with the output text, it also returns character index mapping between input and output texts.";
|
||||
auto transet = oatpp::Vector<UInt16>::createShared();
|
||||
transet->push_back(ZRCOLA_TRANSETID_DEFAULT);
|
||||
auto dto = dto::TranslateIn::createShared();
|
||||
dto->transet = transet;
|
||||
dto->text = "To je test.";
|
||||
info->addConsumes<Object<dto::TranslateIn>>("application/json")
|
||||
.addExample("Perform ZRCola composition", dto);
|
||||
info->addResponse<Object<dto::TranslateOut>>(Status::CODE_200, "application/json");
|
||||
}
|
||||
ENDPOINT("POST", "/translate", postTranslate, BODY_DTO(Object<dto::TranslateIn>, input))
|
||||
{
|
||||
try {
|
||||
utf8toutf16 cIn;
|
||||
@ -112,7 +145,7 @@ public:
|
||||
}
|
||||
|
||||
utf16toutf8 cOut;
|
||||
auto dto = translateOutDto::createShared();
|
||||
auto dto = dto::TranslateOut::createShared();
|
||||
dto->text = cOut.convert(dst);
|
||||
auto map = oatpp::Vector<oatpp::UInt32>::createShared();
|
||||
auto m_end = mapping.cend();
|
||||
@ -131,7 +164,22 @@ public:
|
||||
}
|
||||
|
||||
ADD_CORS(postTranslateInv)
|
||||
ENDPOINT("POST", "/translateInv", postTranslateInv, BODY_DTO(Object<translateInDto>, input))
|
||||
ENDPOINT_INFO(postTranslateInv) {
|
||||
info->summary = "Inverse translate text";
|
||||
info->description =
|
||||
"Performs any number of supported translations (see /transet) on a given input text in a sequence in reverse. "
|
||||
"Together with the output text, it also returns character index mapping between input and output texts.";
|
||||
auto transet = oatpp::Vector<UInt16>::createShared();
|
||||
transet->push_back(ZRCOLA_TRANSETID_DEFAULT);
|
||||
auto dto = dto::TranslateIn::createShared();
|
||||
dto->transet = transet;
|
||||
dto->text = "T ťᵉⓢṭ.";
|
||||
dto->lang = "slv";
|
||||
info->addConsumes<Object<dto::TranslateIn>>("application/json")
|
||||
.addExample("Perform ZRCola decomposition", dto);
|
||||
info->addResponse<Object<dto::TranslateOut>>(Status::CODE_200, "application/json");
|
||||
}
|
||||
ENDPOINT("POST", "/translateInv", postTranslateInv, BODY_DTO(Object<dto::TranslateIn>, input))
|
||||
{
|
||||
try {
|
||||
utf8toutf16 cIn;
|
||||
@ -165,7 +213,7 @@ public:
|
||||
}
|
||||
|
||||
utf16toutf8 cOut;
|
||||
auto dto = translateOutDto::createShared();
|
||||
auto dto = dto::TranslateOut::createShared();
|
||||
dto->text = cOut.convert(dst);
|
||||
auto map = oatpp::Vector<oatpp::UInt32>::createShared();
|
||||
auto m_end = mapping.crend();
|
||||
|
@ -5,49 +5,86 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../include/version.h"
|
||||
#include <oatpp/core/data/mapping/type/Object.hpp>
|
||||
#include <oatpp/core/macro/codegen.hpp>
|
||||
#include <oatpp/core/Types.hpp>
|
||||
|
||||
#include OATPP_CODEGEN_BEGIN(DTO)
|
||||
|
||||
class aboutDto : public oatpp::DTO
|
||||
namespace dto {
|
||||
|
||||
class About : public oatpp::DTO
|
||||
{
|
||||
DTO_INIT(aboutDto, DTO)
|
||||
DTO_FIELD(String, vendor) = PRODUCT_CFG_VENDOR;
|
||||
DTO_FIELD(String, application) = PRODUCT_CFG_APPLICATION;
|
||||
DTO_FIELD(String, version) = PRODUCT_VERSION_STR;
|
||||
DTO_INIT(About, DTO)
|
||||
|
||||
DTO_FIELD_INFO(vendor) { info->description = "Application vendor"; }
|
||||
DTO_FIELD(String, vendor);
|
||||
|
||||
DTO_FIELD_INFO(application) { info->description = "Application name"; }
|
||||
DTO_FIELD(String, application);
|
||||
|
||||
DTO_FIELD_INFO(version) { info->description = "Application version"; }
|
||||
DTO_FIELD(String, version);
|
||||
};
|
||||
|
||||
class transetDto : public oatpp::DTO
|
||||
class TranSet : public oatpp::DTO
|
||||
{
|
||||
DTO_INIT(transetDto, DTO)
|
||||
DTO_INIT(TranSet, DTO)
|
||||
|
||||
DTO_FIELD_INFO(set) { info->description = "Translation set ID"; }
|
||||
DTO_FIELD(UInt16, set);
|
||||
|
||||
DTO_FIELD_INFO(src) { info->description = "Input transcript name in English"; }
|
||||
DTO_FIELD(String, src);
|
||||
|
||||
DTO_FIELD_INFO(dst) { info->description = "Output transcript name in English"; }
|
||||
DTO_FIELD(String, dst);
|
||||
};
|
||||
|
||||
class languageDto : public oatpp::DTO
|
||||
class Language : public oatpp::DTO
|
||||
{
|
||||
DTO_INIT(languageDto, DTO)
|
||||
DTO_INIT(Language, DTO)
|
||||
|
||||
DTO_FIELD_INFO(lang) { info->description = "Language ID"; }
|
||||
DTO_FIELD(String, lang);
|
||||
|
||||
DTO_FIELD_INFO(name) { info->description = "Language name in English"; }
|
||||
DTO_FIELD(String, name);
|
||||
};
|
||||
|
||||
class translateInDto : public oatpp::DTO
|
||||
class TranslateIn : public oatpp::DTO
|
||||
{
|
||||
DTO_INIT(translateInDto, DTO)
|
||||
DTO_INIT(TranslateIn, DTO)
|
||||
|
||||
DTO_FIELD_INFO(transet) {
|
||||
info->description = "Array of one or multiple translation set IDs to perform translation on the text. When inverse translating, the translation sets are read in reverse order listed in this array. Use /transet to get IDs of all supported translation sets.";
|
||||
info->required = true;
|
||||
}
|
||||
DTO_FIELD(Vector<UInt16>, transet);
|
||||
|
||||
DTO_FIELD_INFO(text) {
|
||||
info->description = "Text to be translated";
|
||||
info->required = true;
|
||||
}
|
||||
DTO_FIELD(String, text);
|
||||
|
||||
DTO_FIELD_INFO(lang) {
|
||||
info->description = "Language ID of the text to be translated. This is used on inverse translating to skip decomposing language-specific common characters (e.g. č, š, ž in Slovenian, or ä, ö, ü in German). Use /language to get IDs of all supported languages.";
|
||||
}
|
||||
DTO_FIELD(String, lang) = "slv";
|
||||
};
|
||||
|
||||
class translateOutDto : public oatpp::DTO
|
||||
class TranslateOut : public oatpp::DTO
|
||||
{
|
||||
DTO_INIT(translateOutDto, DTO)
|
||||
DTO_INIT(TranslateOut, DTO)
|
||||
|
||||
DTO_FIELD_INFO(text) { info->description = "Translated text"; }
|
||||
DTO_FIELD(String, text);
|
||||
|
||||
DTO_FIELD_INFO(map) { info->description = "Character index mapping between input and translated text. The map[i] value represents the index of the beginning of a character (in translated text) that translated from the character (in the input text) beginning at index i. All input indexes are measured in characters after input string is translated to UTF-16, and all output indexes are measured in characters before output string is translated from UTF-16."; }
|
||||
DTO_FIELD(Vector<UInt32>, map);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include OATPP_CODEGEN_END(DTO)
|
||||
|
@ -1,73 +0,0 @@
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta http-equiv="Content-Language" content="sl">
|
||||
</head>
|
||||
<style>
|
||||
textarea, input[type="text"]
|
||||
{
|
||||
font-family: ZRCola;
|
||||
font-size: 24px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<form method="GET" name="about" action="http://localhost:8000/about">
|
||||
<h1>about</h1>
|
||||
<p><input type="submit" value="Submit"></p>
|
||||
</form>
|
||||
|
||||
<form method="GET" name="transet" action="http://localhost:8000/transet">
|
||||
<h1>transet</h1>
|
||||
<p><input type="submit" value="Submit"></p>
|
||||
</form>
|
||||
|
||||
<form method="GET" name="language" action="http://localhost:8000/language">
|
||||
<h1>language</h1>
|
||||
<p><input type="submit" value="Submit"></p>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
function submitTranslate() {
|
||||
var form = document.translate;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == XMLHttpRequest.DONE)
|
||||
form["res"].value = xhr.responseText;
|
||||
}
|
||||
xhr.open("POST", "http://localhost:8000/translate", true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
xhr.send(form["req"].value);
|
||||
}
|
||||
</script>
|
||||
<form name="translate">
|
||||
<h1>translate</h1>
|
||||
<p>
|
||||
<textarea rows="10" name="req" cols="40">{"transet":[0], "text":"To je test."}</textarea>
|
||||
>>
|
||||
<textarea rows="10" name="res" cols="40"></textarea>
|
||||
</p>
|
||||
<p><input type="submit" value="Submit" onclick="submitTranslate(); return false"><input type="reset" value="Reset"></p>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
function submitTranslateInv() {
|
||||
var form = document.translateInv;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == XMLHttpRequest.DONE)
|
||||
form["res"].value = xhr.responseText;
|
||||
}
|
||||
xhr.open("POST", "http://localhost:8000/translateInv", true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
|
||||
xhr.send(form["req"].value);
|
||||
}
|
||||
</script>
|
||||
<form name="translateInv">
|
||||
<h1>translateInv</h1>
|
||||
<p>
|
||||
<textarea rows="10" name="req" cols="40">{"transet":[0], "text":"T\uE608 \uE9E2\uF605 \u0165\u1D49\u24E2\u1E6D.", "lang": "slv"}</textarea>
|
||||
>>
|
||||
<textarea rows="10" name="res" cols="40"></textarea>
|
||||
</p>
|
||||
<p><input type="submit" value="Submit" onclick="submitTranslateInv(); return false"><input type="reset" value="Reset"></p>
|
||||
</form>
|
||||
</body>
|
@ -6,6 +6,7 @@
|
||||
#include "appcomponent.hpp"
|
||||
#include "controller.hpp"
|
||||
#include "zrcolaws.hpp"
|
||||
#include <oatpp-swagger/Controller.hpp>
|
||||
#include <oatpp/core/base/CommandLineArguments.hpp>
|
||||
#include <oatpp/network/Server.hpp>
|
||||
#include <signal.h>
|
||||
@ -143,10 +144,20 @@ int main(int argc, const char* argv[])
|
||||
sigIntHandler.sa_flags = 0;
|
||||
sigaction(SIGINT, &sigIntHandler, NULL);
|
||||
|
||||
AppComponent components(cmdArgs);
|
||||
oatpp::String host = cmdArgs.getNamedArgumentValue("--host", "localhost");
|
||||
v_uint16 port = oatpp::utils::conversion::strToInt32(cmdArgs.getNamedArgumentValue("--port", "8000"));
|
||||
oatpp::network::Address::Family family = oatpp::network::Address::UNSPEC;
|
||||
if (cmdArgs.hasArgument("-4"))
|
||||
family = oatpp::network::Address::IP_4;
|
||||
else if (cmdArgs.hasArgument("-6"))
|
||||
family = oatpp::network::Address::IP_6;
|
||||
AppComponent components({host, port, family});
|
||||
OATPP_COMPONENT(std::shared_ptr<oatpp::web::server::HttpRouter>, router);
|
||||
OATPP_COMPONENT(std::shared_ptr<Controller>, controller);
|
||||
OATPP_COMPONENT(std::shared_ptr<oatpp::data::mapping::ObjectMapper>, objectMapper);
|
||||
auto controller = std::make_shared<Controller>(objectMapper);
|
||||
router->addController(controller);
|
||||
auto swaggerController = oatpp::swagger::Controller::createShared(controller->getEndpoints());
|
||||
router->addController(swaggerController);
|
||||
OATPP_COMPONENT(std::shared_ptr<oatpp::network::ServerConnectionProvider>, connectionProvider);
|
||||
OATPP_LOGI("ZRColaWS", "Server " PRODUCT_VERSION_STR " starting on %s:%s",
|
||||
connectionProvider->getProperty("host").getData(), connectionProvider->getProperty("port").getData());
|
||||
|
Loading…
x
Reference in New Issue
Block a user