mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-05-28 04:20:51 +00:00
[qt5 server] various improvements (#725)
* Improve handling of all primitive types * Fix missing includes in case of simple APIs * Fix minor error in template function * Remove tabs * Refactor code for simplicity * Remove tabs * rework the router for handling multiple path param * rework router to handle multiple path parameters * rework router to handle multiple path parameters * rework router * Add support for Multi path param * Add comments to code block and remove duplicate parameters * Remove tabs :( * Add missing imports after resolving conflict
This commit is contained in:
parent
219a88e9c6
commit
f802f8b7d7
@ -23,15 +23,19 @@ import io.swagger.v3.parser.util.SchemaTypeUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CodegenConfig;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.CodegenOperation;
|
||||
import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.utils.ModelUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -55,7 +59,7 @@ public class CppQt5QHttpEngineServerCodegen extends AbstractCppCodegen implement
|
||||
protected Map<String, String> namespaces = new HashMap<String, String>();
|
||||
protected Set<String> systemIncludes = new HashSet<String>();
|
||||
protected String cppNamespace = "OpenAPI";
|
||||
|
||||
protected Set<String> nonFrameworkPrimitives = new HashSet<String>();
|
||||
public CppQt5QHttpEngineServerCodegen() {
|
||||
super();
|
||||
|
||||
@ -135,6 +139,16 @@ public class CppQt5QHttpEngineServerCodegen extends AbstractCppCodegen implement
|
||||
"float",
|
||||
"double")
|
||||
);
|
||||
nonFrameworkPrimitives.addAll(languageSpecificPrimitives);
|
||||
|
||||
foundationClasses.addAll(
|
||||
Arrays.asList(
|
||||
"QString",
|
||||
"QDate",
|
||||
"QDateTime",
|
||||
"QByteArray")
|
||||
);
|
||||
languageSpecificPrimitives.addAll(foundationClasses);
|
||||
|
||||
supportingFiles.add(new SupportingFile("helpers-header.mustache", sourceFolder + MODEL_DIR, PREFIX + "Helpers.h"));
|
||||
supportingFiles.add(new SupportingFile("helpers-body.mustache", sourceFolder + MODEL_DIR, PREFIX + "Helpers.cpp"));
|
||||
@ -174,7 +188,7 @@ public class CppQt5QHttpEngineServerCodegen extends AbstractCppCodegen implement
|
||||
importMapping = new HashMap<String, String>();
|
||||
namespaces = new HashMap<String, String>();
|
||||
|
||||
foundationClasses.add("QString");
|
||||
|
||||
|
||||
systemIncludes.add("QString");
|
||||
systemIncludes.add("QList");
|
||||
@ -434,4 +448,71 @@ public class CppQt5QHttpEngineServerCodegen extends AbstractCppCodegen implement
|
||||
public String getTypeDeclaration(String str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needToImport(String type) {
|
||||
return StringUtils.isNotBlank(type) && !defaultIncludes.contains(type)
|
||||
&& !nonFrameworkPrimitives.contains(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||
Map<String, Object> objectMap = (Map<String, Object>) objs.get("operations");
|
||||
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
|
||||
|
||||
List<Map<String, String>> imports = (List<Map<String, String>>) objs.get("imports");
|
||||
for (CodegenOperation operation : operations) {
|
||||
// Check all return parameter baseType if there is a necessity to include, include it if not
|
||||
// already done
|
||||
if (operation.returnBaseType != null && needToImport(operation.returnBaseType)) {
|
||||
if(!isIncluded(operation.returnBaseType, imports)) {
|
||||
imports.add(createMapping("import", operation.returnBaseType));
|
||||
}
|
||||
}
|
||||
List<CodegenParameter> params = new ArrayList<CodegenParameter>();
|
||||
if (operation.allParams != null)params.addAll(operation.allParams);
|
||||
|
||||
// Check all parameter baseType if there is a necessity to include, include it if not
|
||||
// already done
|
||||
for(CodegenParameter param : params) {
|
||||
if(param.isPrimitiveType && needToImport(param.baseType)) {
|
||||
if(!isIncluded(param.baseType, imports)) {
|
||||
imports.add(createMapping("import", param.baseType));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (operation.pathParams != null) {
|
||||
// We use QString to pass path params, add it to include
|
||||
if(!isIncluded("QString", imports)) {
|
||||
imports.add(createMapping("import", "QString"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isIncluded("QMap", imports)) {
|
||||
// Maps uses QString as key
|
||||
if(!isIncluded("QString", imports)) {
|
||||
imports.add(createMapping("import", "QString"));
|
||||
}
|
||||
}
|
||||
return objs;
|
||||
}
|
||||
|
||||
public Map<String, String> createMapping(String key, String value) {
|
||||
Map<String, String> customImport = new HashMap<String, String>();
|
||||
customImport.put(key, toModelImport(value));
|
||||
return customImport;
|
||||
}
|
||||
|
||||
private boolean isIncluded(String type, List<Map<String, String>> imports) {
|
||||
boolean included = false;
|
||||
String inclStr = toModelImport(type);
|
||||
for (Map<String, String> importItem : imports) {
|
||||
if(importItem.containsValue(inclStr)) {
|
||||
included = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return included;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
# C++ Qt5 Server
|
||||
|
||||
## Qt5 HTTP Server based on the Qhttpengine
|
||||
This server was generated by the [openapi-generator]
|
||||
(https://openapi-generator.tech) project.
|
||||
|
||||
This server was generated by the [openapi-generator](https://openapi-generator.tech) project.
|
||||
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
|
||||
-
|
||||
|
||||
To see how to make this your own, look here:
|
||||
|
||||
@ -25,30 +26,36 @@ Simple set of classes for developing HTTP server applications in Qt.
|
||||
|
||||
To learn more about building and using the library, please visit this page:
|
||||
|
||||
https://ci.quickmediasolutions.com/job/qhttpengine-documentation/doxygen/
|
||||
|
||||
[Link](https://ci.quickmediasolutions.com/job/qhttpengine-documentation/doxygen)
|
||||
|
||||
### Viewing the code
|
||||
|
||||
You can view the code using an editor like Microsoft Visual Studio Code or you can
|
||||
Use QtCreator and browse for the root CMakeLists.txt and load it as a project
|
||||
|
||||
### Build with make
|
||||
|
||||
Install the tools [Linux/Debian]
|
||||
```
|
||||
|
||||
```shell
|
||||
sudo apt install cmake build-essential libssl-dev qtbase5-dev qtbase5-dev-tools git curl
|
||||
```
|
||||
|
||||
To build, go to the `server` folder
|
||||
```
|
||||
|
||||
```shell
|
||||
make
|
||||
```
|
||||
|
||||
To run the server
|
||||
```
|
||||
|
||||
```shell
|
||||
./build/src/cpp-qt5-server &
|
||||
```
|
||||
|
||||
#### Invoke an API
|
||||
```
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:8080/v2/store/inventory
|
||||
curl -X POST http://localhost:8080/v2/store/order -H "Content-Type: application/json" -d "{ \"id\": 22, \"petId\": 1541, \"quantity\": 5, \"shipDate\": \"2018-06-16T18:31:43.870Z\", \"status\": \"placed\", \"complete\": \"true\" }"
|
||||
curl -X GET http://localhost:8080/v2/pet/findByStatus
|
||||
@ -56,38 +63,50 @@ curl -X GET http://localhost:8080/v2/store/inventory
|
||||
```
|
||||
|
||||
### Run and build with docker
|
||||
|
||||
Building with docker multistage
|
||||
If you dont have docker install [here](https://docs.docker.com/install)
|
||||
Add yourself to the docker group
|
||||
|
||||
```
|
||||
```shell
|
||||
docker build --network=host -t cpp-qt5-server .
|
||||
```
|
||||
|
||||
Running with docker
|
||||
```
|
||||
|
||||
```shell
|
||||
docker run --rm -it --name=server-container cpp-qt5-server
|
||||
```
|
||||
|
||||
#### Invoking an API
|
||||
|
||||
Mind the IP here
|
||||
```
|
||||
|
||||
```shell
|
||||
curl -X GET http://172.17.0.2:8080/v2/store/inventory
|
||||
curl -X POST http://172.17.0.2:8080/v2/store/order -H "Content-Type: application/json" -d "{ \"id\": 22, \"petId\": 1541, \"quantity\": 5, \"shipDate\": \"2018-06-16T18:31:43.870Z\", \"status\": \"placed\", \"complete\": \"true\" }"
|
||||
```
|
||||
|
||||
use this command to get the container IP
|
||||
```
|
||||
|
||||
```shell
|
||||
docker inspect server-container | grep "IPAddress"
|
||||
```
|
||||
|
||||
To exit from the command line
|
||||
```
|
||||
|
||||
```shell
|
||||
Ctrl + p + q
|
||||
```
|
||||
|
||||
To stop container
|
||||
```
|
||||
|
||||
```shell
|
||||
docker stop <containername>
|
||||
```
|
||||
|
||||
or to terminate and quit
|
||||
```
|
||||
|
||||
```shell
|
||||
Ctrl+C
|
||||
```
|
||||
|
@ -103,16 +103,18 @@ void {{classname}}Request::{{nickname}}Request({{#hasPathParams}}{{#pathParams}}
|
||||
{{/isListContainer}}
|
||||
{{/bodyParam}}{{/bodyParams}}
|
||||
|
||||
emit {{nickname}}({{#allParams}}{{#isBodyParam}}{{/isBodyParam}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
|
||||
emit {{nickname}}({{#allParams}}{{#isBodyParam}}{{/isBodyParam}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
|
||||
}
|
||||
|
||||
{{/operation}}{{/operations}}
|
||||
|
||||
{{#operations}}{{#operation}}void {{classname}}Request::{{nickname}}Response({{#returnType}}const {{{returnType}}}& res{{/returnType}}){
|
||||
writeResponseHeaders();{{#returnType}}{{^isPrimitiveType}}
|
||||
QJsonDocument resDoc(::{{cppNamespace}}::toJsonValue(res).to{{^isListContainer}}Object{{/isListContainer}}{{#isListContainer}}Array{{/isListContainer}}());{{/isPrimitiveType}}
|
||||
socket->writeJson(resDoc);{{#isPrimitiveType}}
|
||||
socket->write({{#isListContainer}}QString("["+{{/isListContainer}}::{{cppNamespace}}::toStringValue(res){{#isListContainer}}+"]"){{/isListContainer}}.toUtf8());{{/isPrimitiveType}}{{/returnType}}{{^returnType}}
|
||||
writeResponseHeaders();{{#returnType}}{{#isMapContainer}}
|
||||
QJsonDocument resDoc(::{{cppNamespace}}::toJsonValue(res).toObject());
|
||||
socket->writeJson(resDoc);{{/isMapContainer}}{{^isMapContainer}}{{^returnTypeIsPrimitive}}
|
||||
QJsonDocument resDoc(::{{cppNamespace}}::toJsonValue(res).to{{^isListContainer}}Object{{/isListContainer}}{{#isListContainer}}Array{{/isListContainer}}());
|
||||
socket->writeJson(resDoc);{{/returnTypeIsPrimitive}}{{#returnTypeIsPrimitive}}
|
||||
socket->write({{#isListContainer}}QString("["+{{/isListContainer}}::{{cppNamespace}}::toStringValue(res){{#isListContainer}}+"]"){{/isListContainer}}.toUtf8());{{/returnTypeIsPrimitive}}{{/isMapContainer}}{{/returnType}}{{^returnType}}
|
||||
socket->setStatusCode(QHttpEngine::Socket::OK);{{/returnType}}
|
||||
if(socket->isOpen()){
|
||||
socket->close();
|
||||
@ -123,10 +125,12 @@ void {{classname}}Request::{{nickname}}Request({{#hasPathParams}}{{#pathParams}}
|
||||
{{#operations}}{{#operation}}void {{classname}}Request::{{nickname}}Error({{#returnType}}const {{{returnType}}}& res, {{/returnType}}QNetworkReply::NetworkError error_type, QString& error_str){
|
||||
Q_UNUSED(error_type); // TODO: Remap error_type to QHttpEngine::Socket errors
|
||||
writeResponseHeaders();{{#returnType}}
|
||||
Q_UNUSED(error_str); // response will be used instead of error string{{^isPrimitiveType}}
|
||||
QJsonDocument resDoc(::{{cppNamespace}}::toJsonValue(res).to{{^isListContainer}}Object{{/isListContainer}}{{#isListContainer}}Array{{/isListContainer}}());{{/isPrimitiveType}}
|
||||
socket->writeJson(resDoc);{{#isPrimitiveType}}
|
||||
socket->write({{#isListContainer}}QString("["+{{/isListContainer}}::{{cppNamespace}}::toStringValue(res){{#isListContainer}}+"]"){{/isListContainer}}.toUtf8());{{/isPrimitiveType}}{{/returnType}}{{^returnType}}
|
||||
Q_UNUSED(error_str); // response will be used instead of error string{{#isMapContainer}}
|
||||
QJsonDocument resDoc(::{{cppNamespace}}::toJsonValue(res).toObject());
|
||||
socket->writeJson(resDoc);{{/isMapContainer}}{{^isMapContainer}}{{^returnTypeIsPrimitive}}
|
||||
QJsonDocument resDoc(::{{cppNamespace}}::toJsonValue(res).to{{^isListContainer}}Object{{/isListContainer}}{{#isListContainer}}Array{{/isListContainer}}());
|
||||
socket->writeJson(resDoc);{{/returnTypeIsPrimitive}}{{#returnTypeIsPrimitive}}
|
||||
socket->write({{#isListContainer}}QString("["+{{/isListContainer}}::{{cppNamespace}}::toStringValue(res){{#isListContainer}}+"]"){{/isListContainer}}.toUtf8());{{/returnTypeIsPrimitive}}{{/isMapContainer}}{{/returnType}}{{^returnType}}
|
||||
socket->setStatusCode(QHttpEngine::Socket::NotFound);
|
||||
socket->write(error_str.toUtf8());{{/returnType}}
|
||||
if(socket->isOpen()){
|
||||
|
@ -13,80 +13,73 @@
|
||||
namespace {{this}} {
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
inline QHttpEngine::Socket::Method toQHttpEngineMethod(QString method){
|
||||
|
||||
if( method == QString("OPTIONS"))
|
||||
return QHttpEngine::Socket::Method::OPTIONS;
|
||||
if( method == QString("GET"))
|
||||
return QHttpEngine::Socket::Method::GET;
|
||||
if( method == QString("HEAD"))
|
||||
return QHttpEngine::Socket::Method::HEAD;
|
||||
if( method == QString("POST"))
|
||||
return QHttpEngine::Socket::Method::POST;
|
||||
if( method == QString("PUT"))
|
||||
return QHttpEngine::Socket::Method::PUT;
|
||||
if( method == QString("DELETE"))
|
||||
return QHttpEngine::Socket::Method::DELETE;
|
||||
if( method == QString("TRACE"))
|
||||
return QHttpEngine::Socket::Method::TRACE;
|
||||
if( method == QString("CONNECT"))
|
||||
return QHttpEngine::Socket::Method::CONNECT;
|
||||
|
||||
return static_cast<QHttpEngine::Socket::Method>(-1);
|
||||
{{prefix}}ApiRouter::{{prefix}}ApiRouter() {
|
||||
createApiHandlers();
|
||||
}
|
||||
|
||||
ApiRouter::ApiRouter() {
|
||||
{{#apiInfo}}{{#apis}}{{classname}}ApiHandler = new {{classname}}Handler();
|
||||
{{/apis}}{{/apiInfo}}
|
||||
{{prefix}}ApiRouter::~{{prefix}}ApiRouter(){
|
||||
qDebug() << "~ApiRouter()";{{#apiInfo}}{{#apis}}
|
||||
delete {{classname}}ApiHandler;{{/apis}}{{/apiInfo}}
|
||||
}
|
||||
|
||||
ApiRouter::~ApiRouter(){
|
||||
qDebug() << "~ApiRouter()";
|
||||
{{#apiInfo}}{{#apis}}delete {{classname}}ApiHandler;
|
||||
{{/apis}}{{/apiInfo}}
|
||||
void {{prefix}}ApiRouter::createApiHandlers() { {{#apiInfo}}{{#apis}}
|
||||
{{classname}}ApiHandler = new {{classname}}Handler();{{/apis}}{{/apiInfo}}
|
||||
}
|
||||
|
||||
void ApiRouter::setUpRoutes() {
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{^pathParams}}
|
||||
Routes.insert("{{{basePathWithoutHost}}}{{{path}}}",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("{{httpMethod}}") == socket->method()){
|
||||
void {{prefix}}ApiRouter::setUpRoutes() {
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{^hasPathParams}}
|
||||
Routes.insert(QString("%1 %2").arg("{{httpMethod}}").arg("{{{basePathWithoutHost}}}{{{path}}}").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new {{classname}}Request(socket, {{classname}}ApiHandler);
|
||||
reqObj->{{nickname}}Request();
|
||||
}
|
||||
});{{/pathParams}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
});{{/hasPathParams}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
}
|
||||
|
||||
void ApiRouter::processRequest(QHttpEngine::Socket *socket){
|
||||
if (Routes.contains(socket->path())) {
|
||||
for(auto endpoints : Routes.values(socket->path())) {
|
||||
endpoints.operator()(socket);
|
||||
}
|
||||
} else
|
||||
{ {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#pathParams}}
|
||||
{
|
||||
QString completePath("{{{basePathWithoutHost}}}{{{path}}}");
|
||||
QString {{paramName}}PathParam("{");
|
||||
{{paramName}}PathParam.append("{{baseName}}").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace({{paramName}}PathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("{{httpMethod}}") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new {{classname}}Request(socket, {{classname}}ApiHandler);
|
||||
reqObj->{{nickname}}Request({{#hasPathParams}}{{#pathParams}}pathparam{{/pathParams}}{{/hasPathParams}});
|
||||
void {{prefix}}ApiRouter::processRequest(QHttpEngine::Socket *socket){
|
||||
if( handleRequest(socket) ){
|
||||
return;
|
||||
}
|
||||
}{{/pathParams}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
if( handleRequestAndExtractPathParam(socket) ){
|
||||
return;
|
||||
}
|
||||
socket->setStatusCode(QHttpEngine::Socket::NotFound);
|
||||
if(socket->isOpen()){
|
||||
socket->writeHeaders();
|
||||
socket->close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool {{prefix}}ApiRouter::handleRequest(QHttpEngine::Socket *socket){
|
||||
auto reqPath = QString("%1 %2").arg(fromQHttpEngineMethod(socket->method())).arg(socket->path()).toLower();
|
||||
if ( Routes.contains(reqPath) ) {
|
||||
Routes.value(reqPath).operator()(socket);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool {{prefix}}ApiRouter::handleRequestAndExtractPathParam(QHttpEngine::Socket *socket){
|
||||
auto reqPath = QString("%1 %2").arg(fromQHttpEngineMethod(socket->method())).arg(socket->path()).toLower();{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#hasPathParams}}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("{{httpMethod}}").arg("{{{basePathWithoutHost}}}{{{path}}}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
{{#pathParams}}
|
||||
QString {{baseName}} = match.captured(QString("{{baseName}}").toLower());
|
||||
{{/pathParams}}
|
||||
auto reqObj = new {{classname}}Request(socket, {{classname}}ApiHandler);
|
||||
reqObj->{{nickname}}Request({{#pathParams}}{{baseName}}{{#hasMore}}, {{/hasMore}}{{/pathParams}});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}{{/hasPathParams}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
return false;
|
||||
}
|
||||
|
||||
{{#cppNamespaceDeclarations}}
|
||||
}
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
@ -19,7 +19,7 @@
|
||||
namespace {{this}} {
|
||||
{{/cppNamespaceDeclarations}}
|
||||
|
||||
class RequestHandler : public QHttpEngine::QObjectHandler
|
||||
class {{prefix}}ApiRequestHandler : public QHttpEngine::QObjectHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
@ -32,19 +32,51 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
class ApiRouter : public QObject
|
||||
class {{prefix}}ApiRouter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ApiRouter();
|
||||
virtual ~ApiRouter();
|
||||
{{prefix}}ApiRouter();
|
||||
virtual ~{{prefix}}ApiRouter();
|
||||
|
||||
void setUpRoutes();
|
||||
void processRequest(QHttpEngine::Socket *socket);
|
||||
private:
|
||||
QMultiMap<QString, std::function<void(QHttpEngine::Socket *)>> Routes;
|
||||
QMap<QString, std::function<void(QHttpEngine::Socket *)>> Routes;
|
||||
QMultiMap<QString, std::function<void(QHttpEngine::Socket *)>> RoutesWithPathParam;
|
||||
|
||||
bool handleRequest(QHttpEngine::Socket *socket);
|
||||
bool handleRequestAndExtractPathParam(QHttpEngine::Socket *socket);
|
||||
|
||||
{{#apiInfo}}{{#apis}}
|
||||
{{classname}}Handler *{{classname}}ApiHandler;{{/apis}}{{/apiInfo}}
|
||||
protected:
|
||||
// override this method to provide custom class derived from ApiHandler classes
|
||||
virtual void createApiHandlers();
|
||||
|
||||
private :
|
||||
inline QString fromQHttpEngineMethod(QHttpEngine::Socket::Method method){
|
||||
switch( method ){
|
||||
case QHttpEngine::Socket::Method::OPTIONS:
|
||||
return QStringLiteral("OPTIONS");
|
||||
case QHttpEngine::Socket::Method::GET:
|
||||
return QStringLiteral("GET");
|
||||
case QHttpEngine::Socket::Method::HEAD:
|
||||
return QStringLiteral("HEAD");
|
||||
case QHttpEngine::Socket::Method::POST:
|
||||
return QStringLiteral("POST");
|
||||
case QHttpEngine::Socket::Method::PUT:
|
||||
return QStringLiteral("PUT");
|
||||
case QHttpEngine::Socket::Method::DELETE:
|
||||
return QStringLiteral("DELETE");
|
||||
case QHttpEngine::Socket::Method::TRACE:
|
||||
return QStringLiteral("TRACE");
|
||||
case QHttpEngine::Socket::Method::CONNECT:
|
||||
return QStringLiteral("CONNECT");
|
||||
}
|
||||
return QStringLiteral("");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -125,7 +125,7 @@ namespace {{this}} {
|
||||
for(auto itemkey : varmap.keys() ){
|
||||
T itemVal;
|
||||
fromJsonValue(itemVal, QJsonValue::fromVariant(varmap.value(itemkey)));
|
||||
val.insert(itemkey, val);
|
||||
val.insert(itemkey, itemVal);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -70,10 +70,10 @@ int main(int argc, char * argv[])
|
||||
QHostAddress address = QHostAddress(parser.value(addressOption));
|
||||
quint16 port = static_cast<quint16>(parser.value(portOption).toInt());
|
||||
|
||||
QSharedPointer<{{cppNamespace}}::RequestHandler> handler(new {{cppNamespace}}::RequestHandler());
|
||||
{{cppNamespace}}::ApiRouter router;
|
||||
QSharedPointer<{{cppNamespace}}::{{prefix}}ApiRequestHandler> handler(new {{cppNamespace}}::{{prefix}}ApiRequestHandler());
|
||||
{{cppNamespace}}::{{prefix}}ApiRouter router;
|
||||
router.setUpRoutes();
|
||||
QObject::connect(handler.data(), &{{cppNamespace}}::RequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) {
|
||||
QObject::connect(handler.data(), &{{cppNamespace}}::{{prefix}}ApiRequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) {
|
||||
router.processRequest(socket);
|
||||
});
|
||||
|
||||
|
@ -77,7 +77,7 @@ QJsonObject
|
||||
{{classname}}::asJsonObject() const {
|
||||
QJsonObject obj;
|
||||
{{#vars}}
|
||||
{{^isContainer}}{{#complexType}}{{^isString}}{{^isDateTime}}{{^isByteArray}}{{^isDate}}if({{name}}.isSet()){{/isDate}}{{/isByteArray}}{{/isDateTime}}{{/isString}}{{/complexType}}{{^complexType}}if(m_{{name}}_isSet){{/complexType}}{{#isString}}if(m_{{name}}_isSet){{/isString}}{{#isDateTime}}if(m_{{name}}_isSet){{/isDateTime}}{{#isByteArray}}if(m_{{name}}_isSet){{/isByteArray}}{{#isDate}}if(m_{{name}}_isSet){{/isDate}}{
|
||||
{{^isContainer}}{{#complexType}}if({{name}}.isSet()){{/complexType}}{{^complexType}}if(m_{{name}}_isSet){{/complexType}}{
|
||||
obj.insert(QString("{{baseName}}"), ::{{cppNamespace}}::toJsonValue({{name}}));
|
||||
}{{/isContainer}}{{#isContainer}}
|
||||
if({{name}}.size() > 0){
|
||||
@ -105,7 +105,7 @@ bool
|
||||
{{classname}}::isSet() const {
|
||||
bool isObjectUpdated = false;
|
||||
do{ {{#vars}}
|
||||
{{#isContainer}}if({{name}}.size() > 0){{/isContainer}}{{^isContainer}}{{#complexType}}{{^isString}}{{^isDateTime}}{{^isByteArray}}{{^isDate}}if({{name}}.isSet()){{/isDate}}{{/isByteArray}}{{/isDateTime}}{{/isString}}{{/complexType}}{{^complexType}}if(m_{{name}}_isSet){{/complexType}}{{#isString}}if(m_{{name}}_isSet){{/isString}}{{#isDateTime}}if(m_{{name}}_isSet){{/isDateTime}}{{#isByteArray}}if(m_{{name}}_isSet){{/isByteArray}}{{#isDate}}if(m_{{name}}_isSet){{/isDate}}{{/isContainer}}{ isObjectUpdated = true; break;}
|
||||
{{#isContainer}}if({{name}}.size() > 0){{/isContainer}}{{^isContainer}}{{#complexType}}if({{name}}.isSet()){{/complexType}}{{^complexType}}if(m_{{name}}_isSet){{/complexType}}{{/isContainer}}{ isObjectUpdated = true; break;}
|
||||
{{/vars}}}while(false);
|
||||
return isObjectUpdated;
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
# C++ Qt5 Server
|
||||
|
||||
## Qt5 HTTP Server based on the Qhttpengine
|
||||
This server was generated by the [openapi-generator]
|
||||
(https://openapi-generator.tech) project.
|
||||
|
||||
This server was generated by the [openapi-generator](https://openapi-generator.tech) project.
|
||||
By using the [OpenAPI-Spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate a server stub.
|
||||
-
|
||||
|
||||
To see how to make this your own, look here:
|
||||
|
||||
@ -21,30 +22,36 @@ Simple set of classes for developing HTTP server applications in Qt.
|
||||
|
||||
To learn more about building and using the library, please visit this page:
|
||||
|
||||
https://ci.quickmediasolutions.com/job/qhttpengine-documentation/doxygen/
|
||||
|
||||
[Link](https://ci.quickmediasolutions.com/job/qhttpengine-documentation/doxygen)
|
||||
|
||||
### Viewing the code
|
||||
|
||||
You can view the code using an editor like Microsoft Visual Studio Code or you can
|
||||
Use QtCreator and browse for the root CMakeLists.txt and load it as a project
|
||||
|
||||
### Build with make
|
||||
|
||||
Install the tools [Linux/Debian]
|
||||
```
|
||||
|
||||
```shell
|
||||
sudo apt install cmake build-essential libssl-dev qtbase5-dev qtbase5-dev-tools git curl
|
||||
```
|
||||
|
||||
To build, go to the `server` folder
|
||||
```
|
||||
|
||||
```shell
|
||||
make
|
||||
```
|
||||
|
||||
To run the server
|
||||
```
|
||||
|
||||
```shell
|
||||
./build/src/cpp-qt5-server &
|
||||
```
|
||||
|
||||
#### Invoke an API
|
||||
```
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:8080/v2/store/inventory
|
||||
curl -X POST http://localhost:8080/v2/store/order -H "Content-Type: application/json" -d "{ \"id\": 22, \"petId\": 1541, \"quantity\": 5, \"shipDate\": \"2018-06-16T18:31:43.870Z\", \"status\": \"placed\", \"complete\": \"true\" }"
|
||||
curl -X GET http://localhost:8080/v2/pet/findByStatus
|
||||
@ -52,38 +59,50 @@ curl -X GET http://localhost:8080/v2/store/inventory
|
||||
```
|
||||
|
||||
### Run and build with docker
|
||||
|
||||
Building with docker multistage
|
||||
If you dont have docker install [here](https://docs.docker.com/install)
|
||||
Add yourself to the docker group
|
||||
|
||||
```
|
||||
```shell
|
||||
docker build --network=host -t cpp-qt5-server .
|
||||
```
|
||||
|
||||
Running with docker
|
||||
```
|
||||
|
||||
```shell
|
||||
docker run --rm -it --name=server-container cpp-qt5-server
|
||||
```
|
||||
|
||||
#### Invoking an API
|
||||
|
||||
Mind the IP here
|
||||
```
|
||||
|
||||
```shell
|
||||
curl -X GET http://172.17.0.2:8080/v2/store/inventory
|
||||
curl -X POST http://172.17.0.2:8080/v2/store/order -H "Content-Type: application/json" -d "{ \"id\": 22, \"petId\": 1541, \"quantity\": 5, \"shipDate\": \"2018-06-16T18:31:43.870Z\", \"status\": \"placed\", \"complete\": \"true\" }"
|
||||
```
|
||||
|
||||
use this command to get the container IP
|
||||
```
|
||||
|
||||
```shell
|
||||
docker inspect server-container | grep "IPAddress"
|
||||
```
|
||||
|
||||
To exit from the command line
|
||||
```
|
||||
|
||||
```shell
|
||||
Ctrl + p + q
|
||||
```
|
||||
|
||||
To stop container
|
||||
```
|
||||
|
||||
```shell
|
||||
docker stop <containername>
|
||||
```
|
||||
|
||||
or to terminate and quit
|
||||
```
|
||||
|
||||
```shell
|
||||
Ctrl+C
|
||||
```
|
||||
|
@ -24,270 +24,241 @@
|
||||
|
||||
namespace OpenAPI {
|
||||
|
||||
inline QHttpEngine::Socket::Method toQHttpEngineMethod(QString method){
|
||||
|
||||
if( method == QString("OPTIONS"))
|
||||
return QHttpEngine::Socket::Method::OPTIONS;
|
||||
if( method == QString("GET"))
|
||||
return QHttpEngine::Socket::Method::GET;
|
||||
if( method == QString("HEAD"))
|
||||
return QHttpEngine::Socket::Method::HEAD;
|
||||
if( method == QString("POST"))
|
||||
return QHttpEngine::Socket::Method::POST;
|
||||
if( method == QString("PUT"))
|
||||
return QHttpEngine::Socket::Method::PUT;
|
||||
if( method == QString("DELETE"))
|
||||
return QHttpEngine::Socket::Method::DELETE;
|
||||
if( method == QString("TRACE"))
|
||||
return QHttpEngine::Socket::Method::TRACE;
|
||||
if( method == QString("CONNECT"))
|
||||
return QHttpEngine::Socket::Method::CONNECT;
|
||||
|
||||
return static_cast<QHttpEngine::Socket::Method>(-1);
|
||||
OAIApiRouter::OAIApiRouter() {
|
||||
createApiHandlers();
|
||||
}
|
||||
|
||||
ApiRouter::ApiRouter() {
|
||||
OAIPetApiApiHandler = new OAIPetApiHandler();
|
||||
OAIStoreApiApiHandler = new OAIStoreApiHandler();
|
||||
OAIUserApiApiHandler = new OAIUserApiHandler();
|
||||
|
||||
}
|
||||
|
||||
ApiRouter::~ApiRouter(){
|
||||
OAIApiRouter::~OAIApiRouter(){
|
||||
qDebug() << "~ApiRouter()";
|
||||
delete OAIPetApiApiHandler;
|
||||
delete OAIStoreApiApiHandler;
|
||||
delete OAIUserApiApiHandler;
|
||||
|
||||
}
|
||||
|
||||
void ApiRouter::setUpRoutes() {
|
||||
void OAIApiRouter::createApiHandlers() {
|
||||
OAIPetApiApiHandler = new OAIPetApiHandler();
|
||||
OAIStoreApiApiHandler = new OAIStoreApiHandler();
|
||||
OAIUserApiApiHandler = new OAIUserApiHandler();
|
||||
}
|
||||
|
||||
Routes.insert("/v2/pet",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("POST") == socket->method()){
|
||||
void OAIApiRouter::setUpRoutes() {
|
||||
|
||||
Routes.insert(QString("%1 %2").arg("POST").arg("/v2/pet").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->addPetRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/pet/findByStatus",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("GET") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("GET").arg("/v2/pet/findByStatus").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->findPetsByStatusRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/pet/findByTags",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("GET") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("GET").arg("/v2/pet/findByTags").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->findPetsByTagsRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/pet",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("PUT") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("PUT").arg("/v2/pet").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->updatePetRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/store/inventory",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("GET") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("GET").arg("/v2/store/inventory").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIStoreApiRequest(socket, OAIStoreApiApiHandler);
|
||||
reqObj->getInventoryRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/store/order",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("POST") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("POST").arg("/v2/store/order").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIStoreApiRequest(socket, OAIStoreApiApiHandler);
|
||||
reqObj->placeOrderRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/user",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("POST") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("POST").arg("/v2/user").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->createUserRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/user/createWithArray",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("POST") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("POST").arg("/v2/user/createWithArray").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->createUsersWithArrayInputRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/user/createWithList",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("POST") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("POST").arg("/v2/user/createWithList").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->createUsersWithListInputRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/user/login",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("GET") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("GET").arg("/v2/user/login").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->loginUserRequest();
|
||||
}
|
||||
});
|
||||
Routes.insert("/v2/user/logout",[this](QHttpEngine::Socket *socket) {
|
||||
if(toQHttpEngineMethod("GET") == socket->method()){
|
||||
Routes.insert(QString("%1 %2").arg("GET").arg("/v2/user/logout").toLower(), [this](QHttpEngine::Socket *socket) {
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->logoutUserRequest();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void ApiRouter::processRequest(QHttpEngine::Socket *socket){
|
||||
if (Routes.contains(socket->path())) {
|
||||
for(auto endpoints : Routes.values(socket->path())) {
|
||||
endpoints.operator()(socket);
|
||||
}
|
||||
} else
|
||||
{
|
||||
{
|
||||
QString completePath("/v2/pet/{petId}");
|
||||
QString pet_idPathParam("{");
|
||||
pet_idPathParam.append("petId").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(pet_idPathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("DELETE") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->deletePetRequest(pathparam);;
|
||||
void OAIApiRouter::processRequest(QHttpEngine::Socket *socket){
|
||||
if( handleRequest(socket) ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString completePath("/v2/pet/{petId}");
|
||||
QString pet_idPathParam("{");
|
||||
pet_idPathParam.append("petId").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(pet_idPathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("GET") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->getPetByIdRequest(pathparam);;
|
||||
if( handleRequestAndExtractPathParam(socket) ){
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString completePath("/v2/pet/{petId}");
|
||||
QString pet_idPathParam("{");
|
||||
pet_idPathParam.append("petId").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(pet_idPathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("POST") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->updatePetWithFormRequest(pathparam);;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString completePath("/v2/pet/{petId}/uploadImage");
|
||||
QString pet_idPathParam("{");
|
||||
pet_idPathParam.append("petId").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(pet_idPathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("POST") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->uploadFileRequest(pathparam);;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString completePath("/v2/store/order/{orderId}");
|
||||
QString order_idPathParam("{");
|
||||
order_idPathParam.append("orderId").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(order_idPathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("DELETE") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIStoreApiRequest(socket, OAIStoreApiApiHandler);
|
||||
reqObj->deleteOrderRequest(pathparam);;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString completePath("/v2/store/order/{orderId}");
|
||||
QString order_idPathParam("{");
|
||||
order_idPathParam.append("orderId").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(order_idPathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("GET") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIStoreApiRequest(socket, OAIStoreApiApiHandler);
|
||||
reqObj->getOrderByIdRequest(pathparam);;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString completePath("/v2/user/{username}");
|
||||
QString usernamePathParam("{");
|
||||
usernamePathParam.append("username").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(usernamePathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("DELETE") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->deleteUserRequest(pathparam);;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString completePath("/v2/user/{username}");
|
||||
QString usernamePathParam("{");
|
||||
usernamePathParam.append("username").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(usernamePathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("GET") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->getUserByNameRequest(pathparam);;
|
||||
return;
|
||||
}
|
||||
}
|
||||
{
|
||||
QString completePath("/v2/user/{username}");
|
||||
QString usernamePathParam("{");
|
||||
usernamePathParam.append("username").append("}");
|
||||
completePath.replace("/", "\\/"); // replace '/' with '\/' for regex
|
||||
completePath.replace(usernamePathParam, "([^\\/]*?)"); // match anything but '/''
|
||||
completePath.append("$"); // End of string
|
||||
QRegularExpression re(completePath, QRegularExpression::CaseInsensitiveOption);
|
||||
QRegularExpressionMatch match = re.match(socket->path());
|
||||
if ((toQHttpEngineMethod("PUT") == socket->method()) && match.hasMatch() ) {
|
||||
QString pathparam = match.captured(1);
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->updateUserRequest(pathparam);;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
socket->setStatusCode(QHttpEngine::Socket::NotFound);
|
||||
if(socket->isOpen()){
|
||||
socket->writeHeaders();
|
||||
socket->close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool OAIApiRouter::handleRequest(QHttpEngine::Socket *socket){
|
||||
auto reqPath = QString("%1 %2").arg(fromQHttpEngineMethod(socket->method())).arg(socket->path()).toLower();
|
||||
if ( Routes.contains(reqPath) ) {
|
||||
Routes.value(reqPath).operator()(socket);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OAIApiRouter::handleRequestAndExtractPathParam(QHttpEngine::Socket *socket){
|
||||
auto reqPath = QString("%1 %2").arg(fromQHttpEngineMethod(socket->method())).arg(socket->path()).toLower();
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("DELETE").arg("/v2/pet/{petId}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString petId = match.captured(QString("petId").toLower());
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->deletePetRequest(petId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("GET").arg("/v2/pet/{petId}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString petId = match.captured(QString("petId").toLower());
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->getPetByIdRequest(petId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("POST").arg("/v2/pet/{petId}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString petId = match.captured(QString("petId").toLower());
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->updatePetWithFormRequest(petId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("POST").arg("/v2/pet/{petId}/uploadImage").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString petId = match.captured(QString("petId").toLower());
|
||||
auto reqObj = new OAIPetApiRequest(socket, OAIPetApiApiHandler);
|
||||
reqObj->uploadFileRequest(petId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("DELETE").arg("/v2/store/order/{orderId}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString orderId = match.captured(QString("orderId").toLower());
|
||||
auto reqObj = new OAIStoreApiRequest(socket, OAIStoreApiApiHandler);
|
||||
reqObj->deleteOrderRequest(orderId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("GET").arg("/v2/store/order/{orderId}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString orderId = match.captured(QString("orderId").toLower());
|
||||
auto reqObj = new OAIStoreApiRequest(socket, OAIStoreApiApiHandler);
|
||||
reqObj->getOrderByIdRequest(orderId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("DELETE").arg("/v2/user/{username}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString username = match.captured(QString("username").toLower());
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->deleteUserRequest(username);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("GET").arg("/v2/user/{username}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString username = match.captured(QString("username").toLower());
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->getUserByNameRequest(username);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto completePath = QString("%1 %2").arg("PUT").arg("/v2/user/{username}").toLower();
|
||||
if ( reqPath.startsWith(completePath.leftRef( completePath.indexOf(QString("/{")))) ) {
|
||||
QRegularExpression parExpr( R"(\{([^\/\\s]+)\})" );
|
||||
completePath.replace( parExpr, R"((?<\1>[^\/\s]+))" );
|
||||
completePath.append("[\\/]?$");
|
||||
QRegularExpression pathExpr( completePath );
|
||||
QRegularExpressionMatch match = pathExpr.match( reqPath );
|
||||
if ( match.hasMatch() ){
|
||||
QString username = match.captured(QString("username").toLower());
|
||||
auto reqObj = new OAIUserApiRequest(socket, OAIUserApiApiHandler);
|
||||
reqObj->updateUserRequest(username);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
namespace OpenAPI {
|
||||
|
||||
class RequestHandler : public QHttpEngine::QObjectHandler
|
||||
class OAIApiRequestHandler : public QHttpEngine::QObjectHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
@ -43,21 +43,53 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
class ApiRouter : public QObject
|
||||
class OAIApiRouter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ApiRouter();
|
||||
virtual ~ApiRouter();
|
||||
OAIApiRouter();
|
||||
virtual ~OAIApiRouter();
|
||||
|
||||
void setUpRoutes();
|
||||
void processRequest(QHttpEngine::Socket *socket);
|
||||
private:
|
||||
QMultiMap<QString, std::function<void(QHttpEngine::Socket *)>> Routes;
|
||||
QMap<QString, std::function<void(QHttpEngine::Socket *)>> Routes;
|
||||
QMultiMap<QString, std::function<void(QHttpEngine::Socket *)>> RoutesWithPathParam;
|
||||
|
||||
bool handleRequest(QHttpEngine::Socket *socket);
|
||||
bool handleRequestAndExtractPathParam(QHttpEngine::Socket *socket);
|
||||
|
||||
|
||||
OAIPetApiHandler *OAIPetApiApiHandler;
|
||||
OAIStoreApiHandler *OAIStoreApiApiHandler;
|
||||
OAIUserApiHandler *OAIUserApiApiHandler;
|
||||
protected:
|
||||
// override this method to provide custom class derived from ApiHandler classes
|
||||
virtual void createApiHandlers();
|
||||
|
||||
private :
|
||||
inline QString fromQHttpEngineMethod(QHttpEngine::Socket::Method method){
|
||||
switch( method ){
|
||||
case QHttpEngine::Socket::Method::OPTIONS:
|
||||
return QStringLiteral("OPTIONS");
|
||||
case QHttpEngine::Socket::Method::GET:
|
||||
return QStringLiteral("GET");
|
||||
case QHttpEngine::Socket::Method::HEAD:
|
||||
return QStringLiteral("HEAD");
|
||||
case QHttpEngine::Socket::Method::POST:
|
||||
return QStringLiteral("POST");
|
||||
case QHttpEngine::Socket::Method::PUT:
|
||||
return QStringLiteral("PUT");
|
||||
case QHttpEngine::Socket::Method::DELETE:
|
||||
return QStringLiteral("DELETE");
|
||||
case QHttpEngine::Socket::Method::TRACE:
|
||||
return QStringLiteral("TRACE");
|
||||
case QHttpEngine::Socket::Method::CONNECT:
|
||||
return QStringLiteral("CONNECT");
|
||||
}
|
||||
return QStringLiteral("");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -81,10 +81,10 @@ int main(int argc, char * argv[])
|
||||
QHostAddress address = QHostAddress(parser.value(addressOption));
|
||||
quint16 port = static_cast<quint16>(parser.value(portOption).toInt());
|
||||
|
||||
QSharedPointer<OpenAPI::RequestHandler> handler(new OpenAPI::RequestHandler());
|
||||
OpenAPI::ApiRouter router;
|
||||
QSharedPointer<OpenAPI::OAIApiRequestHandler> handler(new OpenAPI::OAIApiRequestHandler());
|
||||
OpenAPI::OAIApiRouter router;
|
||||
router.setUpRoutes();
|
||||
QObject::connect(handler.data(), &OpenAPI::RequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) {
|
||||
QObject::connect(handler.data(), &OpenAPI::OAIApiRequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) {
|
||||
router.processRequest(socket);
|
||||
});
|
||||
|
||||
|
@ -134,7 +134,7 @@ namespace OpenAPI {
|
||||
for(auto itemkey : varmap.keys() ){
|
||||
T itemVal;
|
||||
fromJsonValue(itemVal, QJsonValue::fromVariant(varmap.value(itemkey)));
|
||||
val.insert(itemkey, val);
|
||||
val.insert(itemkey, itemVal);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -63,7 +63,7 @@ void OAIPetApiRequest::addPetRequest(){
|
||||
::OpenAPI::fromJsonValue(oai_pet, obj);
|
||||
|
||||
|
||||
emit addPet( oai_pet);
|
||||
emit addPet(oai_pet);
|
||||
}
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ void OAIPetApiRequest::deletePetRequest(const QString& pet_idstr){
|
||||
}
|
||||
|
||||
|
||||
emit deletePet( pet_id, api_key);
|
||||
emit deletePet(pet_id, api_key);
|
||||
}
|
||||
|
||||
|
||||
@ -97,7 +97,7 @@ void OAIPetApiRequest::findPetsByStatusRequest(){
|
||||
|
||||
|
||||
|
||||
emit findPetsByStatus( status);
|
||||
emit findPetsByStatus(status);
|
||||
}
|
||||
|
||||
|
||||
@ -113,7 +113,7 @@ void OAIPetApiRequest::findPetsByTagsRequest(){
|
||||
|
||||
|
||||
|
||||
emit findPetsByTags( tags);
|
||||
emit findPetsByTags(tags);
|
||||
}
|
||||
|
||||
|
||||
@ -126,7 +126,7 @@ void OAIPetApiRequest::getPetByIdRequest(const QString& pet_idstr){
|
||||
fromStringValue(pet_idstr, pet_id);
|
||||
|
||||
|
||||
emit getPetById( pet_id);
|
||||
emit getPetById(pet_id);
|
||||
}
|
||||
|
||||
|
||||
@ -143,7 +143,7 @@ void OAIPetApiRequest::updatePetRequest(){
|
||||
::OpenAPI::fromJsonValue(oai_pet, obj);
|
||||
|
||||
|
||||
emit updatePet( oai_pet);
|
||||
emit updatePet(oai_pet);
|
||||
}
|
||||
|
||||
|
||||
@ -158,7 +158,7 @@ void OAIPetApiRequest::updatePetWithFormRequest(const QString& pet_idstr){
|
||||
QString name;
|
||||
QString status;
|
||||
|
||||
emit updatePetWithForm( pet_id, name, status);
|
||||
emit updatePetWithForm(pet_id, name, status);
|
||||
}
|
||||
|
||||
|
||||
@ -173,7 +173,7 @@ void OAIPetApiRequest::uploadFileRequest(const QString& pet_idstr){
|
||||
QString additional_metadata;
|
||||
QIODevice* file;
|
||||
|
||||
emit uploadFile( pet_id, additional_metadata, file);
|
||||
emit uploadFile(pet_id, additional_metadata, file);
|
||||
}
|
||||
|
||||
|
||||
|
@ -59,7 +59,7 @@ void OAIStoreApiRequest::deleteOrderRequest(const QString& order_idstr){
|
||||
fromStringValue(order_idstr, order_id);
|
||||
|
||||
|
||||
emit deleteOrder( order_id);
|
||||
emit deleteOrder(order_id);
|
||||
}
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@ void OAIStoreApiRequest::getOrderByIdRequest(const QString& order_idstr){
|
||||
fromStringValue(order_idstr, order_id);
|
||||
|
||||
|
||||
emit getOrderById( order_id);
|
||||
emit getOrderById(order_id);
|
||||
}
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@ void OAIStoreApiRequest::placeOrderRequest(){
|
||||
::OpenAPI::fromJsonValue(oai_order, obj);
|
||||
|
||||
|
||||
emit placeOrder( oai_order);
|
||||
emit placeOrder(oai_order);
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,7 +63,7 @@ void OAIUserApiRequest::createUserRequest(){
|
||||
::OpenAPI::fromJsonValue(oai_user, obj);
|
||||
|
||||
|
||||
emit createUser( oai_user);
|
||||
emit createUser(oai_user);
|
||||
}
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@ void OAIUserApiRequest::createUsersWithArrayInputRequest(){
|
||||
}
|
||||
|
||||
|
||||
emit createUsersWithArrayInput( oai_user);
|
||||
emit createUsersWithArrayInput(oai_user);
|
||||
}
|
||||
|
||||
|
||||
@ -107,7 +107,7 @@ void OAIUserApiRequest::createUsersWithListInputRequest(){
|
||||
}
|
||||
|
||||
|
||||
emit createUsersWithListInput( oai_user);
|
||||
emit createUsersWithListInput(oai_user);
|
||||
}
|
||||
|
||||
|
||||
@ -120,7 +120,7 @@ void OAIUserApiRequest::deleteUserRequest(const QString& usernamestr){
|
||||
fromStringValue(usernamestr, username);
|
||||
|
||||
|
||||
emit deleteUser( username);
|
||||
emit deleteUser(username);
|
||||
}
|
||||
|
||||
|
||||
@ -133,7 +133,7 @@ void OAIUserApiRequest::getUserByNameRequest(const QString& usernamestr){
|
||||
fromStringValue(usernamestr, username);
|
||||
|
||||
|
||||
emit getUserByName( username);
|
||||
emit getUserByName(username);
|
||||
}
|
||||
|
||||
|
||||
@ -154,7 +154,7 @@ void OAIUserApiRequest::loginUserRequest(){
|
||||
|
||||
|
||||
|
||||
emit loginUser( username, password);
|
||||
emit loginUser(username, password);
|
||||
}
|
||||
|
||||
|
||||
@ -184,7 +184,7 @@ void OAIUserApiRequest::updateUserRequest(const QString& usernamestr){
|
||||
::OpenAPI::fromJsonValue(oai_user, obj);
|
||||
|
||||
|
||||
emit updateUser( username, oai_user);
|
||||
emit updateUser(username, oai_user);
|
||||
}
|
||||
|
||||
|
||||
@ -232,8 +232,7 @@ void OAIUserApiRequest::getUserByNameResponse(const OAIUser& res){
|
||||
|
||||
void OAIUserApiRequest::loginUserResponse(const QString& res){
|
||||
writeResponseHeaders();
|
||||
QJsonDocument resDoc(::OpenAPI::toJsonValue(res).toObject());
|
||||
socket->writeJson(resDoc);
|
||||
socket->write(::OpenAPI::toStringValue(res).toUtf8());
|
||||
if(socket->isOpen()){
|
||||
socket->close();
|
||||
}
|
||||
@ -311,8 +310,7 @@ void OAIUserApiRequest::loginUserError(const QString& res, QNetworkReply::Networ
|
||||
Q_UNUSED(error_type); // TODO: Remap error_type to QHttpEngine::Socket errors
|
||||
writeResponseHeaders();
|
||||
Q_UNUSED(error_str); // response will be used instead of error string
|
||||
QJsonDocument resDoc(::OpenAPI::toJsonValue(res).toObject());
|
||||
socket->writeJson(resDoc);
|
||||
socket->write(::OpenAPI::toStringValue(res).toUtf8());
|
||||
if(socket->isOpen()){
|
||||
socket->close();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user