Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[qt5 server] Improvement in response handling #675

Merged
merged 10 commits into from
Jul 30, 2018
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import java.util.Set;

public class CppQt5QHttpEngineServerCodegen extends AbstractCppCodegen implements CodegenConfig {
@SuppressWarnings("unused")
private static final Logger LOGGER = LoggerFactory.getLogger(CppQt5QHttpEngineServerCodegen.class);

public static final String CPP_NAMESPACE = "cppNamespace";
Expand Down Expand Up @@ -234,7 +235,7 @@ public String getName() {
}

/**
* Returns human-friendly help for the generator. Provide the consumer with help
* Returns human-friendly help for the generator. Provide the consumer with help
* tips, parameters here
*
* @return A string value for the help message
Expand Down Expand Up @@ -262,21 +263,7 @@ public String toModelImport(String name) {

return "#include \"" + folder + name + ".h\"";
}

/**
* Escapes a reserved word as defined in the `reservedWords` array. Handle escaping
* those terms here. This logic is only called if a variable matches the reserved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
if (this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}


/**
* Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated
Expand Down Expand Up @@ -327,6 +314,7 @@ public String toApiFilename(String name) {
* @return a string value used as the `dataType` field for model templates, `returnType` for api templates
*/
@Override
@SuppressWarnings("rawtypes")
public String getTypeDeclaration(Schema p) {
String openAPIType = getSchemaType(p);

Expand All @@ -352,6 +340,7 @@ public String getTypeDeclaration(Schema p) {
}

@Override
@SuppressWarnings("rawtypes")
public String toDefaultValue(Schema p) {
if (ModelUtils.isBooleanSchema(p)) {
return "false";
Expand Down Expand Up @@ -391,6 +380,7 @@ public String toDefaultValue(Schema p) {
* @return a string value of the type or complex model for this property
*/
@Override
@SuppressWarnings("rawtypes")
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);

Expand All @@ -409,24 +399,6 @@ public String getSchemaType(Schema p) {
return toModelName(type);
}

@Override
public String toModelName(String type) {
if (type == null) {
LOGGER.warn("Model name can't be null. Defaul to 'UnknownModel'.");
type = "UnknownModel";
}

if (typeMapping.keySet().contains(type) ||
typeMapping.values().contains(type) ||
importMapping.values().contains(type) ||
defaultIncludes.contains(type) ||
languageSpecificPrimitives.contains(type)) {
return type;
} else {
return modelNamePrefix + Character.toUpperCase(type.charAt(0)) + type.substring(1);
}
}

@Override
public String toVarName(String name) {
// sanitize name
Expand Down Expand Up @@ -455,22 +427,6 @@ public String toParamName(String name) {
return toVarName(name);
}

@Override
public String toApiName(String type) {
return modelNamePrefix + Character.toUpperCase(type.charAt(0)) + type.substring(1) + "Api";
}

@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}

@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}

@Override
public String getTypeDeclaration(String str) {
return str;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{{>licenseInfo}}
#ifndef _{{prefix}}_{{classname}}Handler_H_
#define _{{prefix}}_{{classname}}Handler_H_
#ifndef {{prefix}}_{{classname}}Handler_H
#define {{prefix}}_{{classname}}Handler_H

#include <QObject>

Expand Down Expand Up @@ -30,4 +30,4 @@ public slots:
}
{{/cppNamespaceDeclarations}}

#endif // _{{prefix}}_{{classname}}Handler_H_
#endif // {{prefix}}_{{classname}}Handler_H
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ namespace {{this}} {
{{/cppNamespaceDeclarations}}

{{classname}}Request::{{classname}}Request(QHttpEngine::Socket *s, {{classname}}Handler* hdl) : QObject(s), socket(s), handler(hdl) {
auto headers = s->headers();
for(auto itr = headers.begin(); itr != headers.end(); itr++) {
requestHeaders.insert(QString(itr.key()), QString(itr.value()));
}
}

{{classname}}Request::~{{classname}}Request(){
Expand All @@ -21,16 +25,23 @@ namespace {{this}} {
}

QMap<QString, QString>
{{classname}}Request::getDefaultHeaders(){
return defaultHeaders;
{{classname}}Request::getRequestHeaders() const {
return requestHeaders;
}

void {{classname}}Request::setResponseHeaders(const QMultiMap<QString, QString>& headers){
for(auto itr = headers.begin(); itr != headers.end(); ++itr) {
responseHeaders.insert(itr.key(), itr.value());
}
}


QHttpEngine::Socket* {{classname}}Request::getRawSocket(){
return socket;
}

{{#operations}}{{#operation}}
void {{classname}}Request::{{nickname}}Request({{#hasPathParams}}{{#pathParams}}QString {{{paramName}}}str{{/pathParams}}{{/hasPathParams}}){
void {{classname}}Request::{{nickname}}Request({{#hasPathParams}}{{#pathParams}}const QString& {{{paramName}}}str{{#hasMore}}, {{/hasMore}}{{/pathParams}}{{/hasPathParams}}){
qDebug() << "{{{basePathWithoutHost}}}{{{path}}}";
connect(this, &{{classname}}Request::{{nickname}}, handler, &{{classname}}Handler::{{nickname}});

Expand Down Expand Up @@ -64,10 +75,10 @@ void {{classname}}Request::{{nickname}}Request({{#hasPathParams}}{{#pathParams}}
{{/isListContainer}}
{{^isListContainer}}
{{^isMapContainer}}
{{#isPrimitive}}
{{#isPrimitiveType}}
{{{dataType}}} {{paramName}};
::{{cppNamespace}}::fromStringValue((QString(socket->readAll()), {{paramName}});
{{/isPrimitive}}
{{/isPrimitiveType}}
{{/isMapContainer}}
{{#isMapContainer}}
QJsonDocument doc;
Expand All @@ -81,13 +92,13 @@ void {{classname}}Request::{{nickname}}Request({{#hasPathParams}}{{#pathParams}}
}
{{/isMapContainer}}
{{^isMapContainer}}
{{^isPrimitive}}
{{^isPrimitiveType}}
QJsonDocument doc;
socket->readJson(doc);
QJsonObject obj = doc.object();
{{{dataType}}} {{paramName}};
::{{cppNamespace}}::fromJsonValue({{paramName}}, obj);
{{/isPrimitive}}
{{/isPrimitiveType}}
{{/isMapContainer}}
{{/isListContainer}}
{{/bodyParam}}{{/bodyParams}}
Expand All @@ -97,27 +108,42 @@ void {{classname}}Request::{{nickname}}Request({{#hasPathParams}}{{#pathParams}}

{{/operation}}{{/operations}}

{{#operations}}{{#operation}}void {{classname}}Request::{{nickname}}Response({{#returnType}}{{{returnType}}} res{{/returnType}}){
socket->setStatusCode(QHttpEngine::Socket::OK);
{{#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}}
socket->setStatusCode(QHttpEngine::Socket::OK);{{/returnType}}
if(socket->isOpen()){
socket->writeHeaders();
socket->close();
}
}
{{/operation}}{{/operations}}

{{#operations}}{{#operation}}void {{classname}}Request::{{nickname}}Error({{#returnType}}{{{returnType}}} res, {{/returnType}}QNetworkReply::NetworkError error_type, QString& error_str){
Q_UNUSED(error_type);
Q_UNUSED(error_str);
{{/operation}}{{/operations}}
{{#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}}
socket->setStatusCode(QHttpEngine::Socket::NotFound);
socket->write(error_str.toUtf8());{{/returnType}}
if(socket->isOpen()){
socket->writeHeaders();
socket->close();
}
}
{{/operation}}{{/operations}}


{{/operation}}{{/operations}}
void {{classname}}Request::sendCustomResponse(QByteArray & res, QNetworkReply::NetworkError error_type){
Q_UNUSED(res); // TODO
Q_UNUSED(error_type); // TODO
}

void {{classname}}Request::sendCustomResponse(QIODevice *res, QNetworkReply::NetworkError error_type){
Q_UNUSED(res); // TODO
Q_UNUSED(error_type); // TODO
}

{{#cppNamespaceDeclarations}}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{{>licenseInfo}}
#ifndef _{{prefix}}_{{classname}}Request_H_
#define _{{prefix}}_{{classname}}Request_H_
#ifndef {{prefix}}_{{classname}}Request_H
#define {{prefix}}_{{classname}}Request_H

#include <QObject>
#include <QStringList>
#include <QMultiMap>
#include <QNetworkReply>
#include <QSharedPointer>

Expand All @@ -24,30 +25,47 @@ public:
{{classname}}Request(QHttpEngine::Socket *s, {{classname}}Handler* handler);
virtual ~{{classname}}Request();

{{#operations}}{{#operation}}void {{nickname}}Request({{#hasPathParams}}{{#pathParams}}QString {{{paramName}}}{{/pathParams}}{{/hasPathParams}});
{{#operations}}{{#operation}}void {{nickname}}Request({{#hasPathParams}}{{#pathParams}}const QString& {{{paramName}}}{{#hasMore}}, {{/hasMore}}{{/pathParams}}{{/hasPathParams}});
{{/operation}}{{/operations}}

{{#operations}}{{#operation}}void {{nickname}}Response({{#returnType}}{{{returnType}}} res{{/returnType}});
{{#operations}}{{#operation}}void {{nickname}}Response({{#returnType}}const {{{returnType}}}& res{{/returnType}});
{{/operation}}{{/operations}}

{{#operations}}{{#operation}}void {{nickname}}Error({{#returnType}}{{{returnType}}} res, {{/returnType}}QNetworkReply::NetworkError error_type, QString& error_str);
{{#operations}}{{#operation}}void {{nickname}}Error({{#returnType}}const {{{returnType}}}& res, {{/returnType}}QNetworkReply::NetworkError error_type, QString& error_str);
{{/operation}}{{/operations}}

QMap<QString, QString> getDefaultHeaders();
void sendCustomResponse(QByteArray & res, QNetworkReply::NetworkError error_type);

void sendCustomResponse(QIODevice *res, QNetworkReply::NetworkError error_type);

QMap<QString, QString> getRequestHeaders() const;

QHttpEngine::Socket* getRawSocket();

void setResponseHeaders(const QMultiMap<QString,QString>& headers);

signals:
{{#operations}}{{#operation}}void {{nickname}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{/operation}}{{/operations}}

private:
QMap<QString, QString> defaultHeaders;
QMap<QString, QString> requestHeaders;
QMap<QString, QString> responseHeaders;
QHttpEngine::Socket *socket;
{{classname}}Handler *handler;

inline void writeResponseHeaders(){
QHttpEngine::Socket::HeaderMap resHeaders;
for(auto itr = responseHeaders.begin(); itr != responseHeaders.end(); ++itr) {
resHeaders.insert(itr.key().toUtf8(), itr.value().toUtf8());
}
socket->setHeaders(resHeaders);
socket->writeHeaders();
}
};

{{#cppNamespaceDeclarations}}
}
{{/cppNamespaceDeclarations}}

#endif // _{{prefix}}_{{classname}}Request_H_
#endif // {{prefix}}_{{classname}}Request_H
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,8 @@ void ApiRouter::setUpRoutes() {

void ApiRouter::processRequest(QHttpEngine::Socket *socket){
if (Routes.contains(socket->path())) {
auto itr = Routes.find(socket->path());
while (itr != Routes.end() && itr.key() == socket->path()) {
itr.value().operator()(socket);
++itr;
for(auto endpoints : Routes.values(socket->path())) {
endpoints.operator()(socket);
}
} else
{ {{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}{{#pathParams}}
Expand All @@ -77,7 +75,7 @@ void ApiRouter::processRequest(QHttpEngine::Socket *socket){
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}});;
reqObj->{{nickname}}Request({{#hasPathParams}}{{#pathParams}}pathparam{{/pathParams}}{{/hasPathParams}});
return;
}
}{{/pathParams}}{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,15 @@ namespace {{this}} {
QString toStringValue(const double &value);

template <typename T>
QList<QString> toStringValue(const QList<T> &val) {
QList<QString> strArray;
QString toStringValue(const QList<T> &val) {
QString strArray;
for(auto item : val) {
strArray.append(toStringValue(item));
strArray.append(toStringValue(item) + ",");
}
return strArray;
}

template <typename T>
QMap<QString, QString> toStringValue(const QMap<QString, T> &val) {
QMap<QString, QString> strMap;
for(auto itemkey : val.keys()) {
strMap.insert(itemkey, toStringValue(val.value(itemkey)));
if(val.count() > 0) {
strArray.chop(1);
}
return strMap;
return strArray;
}

QJsonValue toJsonValue(const QString &value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ int main(int argc, char * argv[])

QSharedPointer<{{cppNamespace}}::RequestHandler> handler(new {{cppNamespace}}::RequestHandler());
{{cppNamespace}}::ApiRouter router;
router.setUpRoutes();
QObject::connect(handler.data(), &{{cppNamespace}}::RequestHandler::requestReceived, [&](QHttpEngine::Socket *socket) {
router.processRequest(socket);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ QJsonObject

{{#vars}}
{{{dataType}}}
{{classname}}::{{getter}}() {
{{classname}}::{{getter}}() const {
return {{name}};
}
void
Expand Down
Loading