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,7 +34,8 @@
import java.util.Set;

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

public static final String CPP_NAMESPACE = "cppNamespace";
public static final String CPP_NAMESPACE_DESC = "C++ namespace (convention: name::space::for::api).";
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,10 +25,17 @@ 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;
}
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 @@ -98,26 +109,51 @@ 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);
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();{{#returnType}}{{^isPrimitiveType}}
QJsonDocument resDoc(::{{cppNamespace}}::toJsonValue(res).to{{^isListContainer}}Object{{/isListContainer}}{{#isListContainer}}Array{{/isListContainer}}());{{/isPrimitiveType}}
socket->writeJson(resDoc);{{#isPrimitiveType}}
socket->write(::{{cppNamespace}}::toStringValue(res).toUtf8());{{/isPrimitiveType}}{{/returnType}}{{^returnType}}
Copy link
Contributor Author

@etherealjoy etherealjoy Jul 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wing328 @stkrwork
How is the serialization done for the array/map of primitive types?
Are they comma/CRLF/white space separated?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For restbed i used json arrays

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for json arrays it is OK, I mean if the response is array or map of primitive types.
Beccause they are arrays/maps of strings , how do we indicate it is an array instead of a long string. How is this defined in spec?

socket->setStatusCode(QHttpEngine::Socket::OK);{{/returnType}}
if(socket->isOpen()){
socket->writeHeaders();
socket->close();
}
}
{{/operation}}{{/operations}}

{{/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);
Q_UNUSED(error_type); // TODO: Remap error_type to QHttpEngine::Socket errors
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();{{#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(::{{cppNamespace}}::toStringValue(res).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 Down Expand Up @@ -33,15 +34,23 @@ public:
{{#operations}}{{#operation}}void {{nickname}}Error({{#returnType}}{{{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;
};
Expand All @@ -50,4 +59,4 @@ private:
}
{{/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 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* {{description}}
*/

#ifndef {{classname}}_H_
#define {{classname}}_H_
#ifndef {{classname}}_H
#define {{classname}}_H

#include <QJsonObject>

Expand Down Expand Up @@ -35,7 +35,7 @@ public:
void fromJson(QString jsonString) override;

{{#vars}}
{{{dataType}}} {{getter}}();
{{{dataType}}} {{getter}}() const;
void {{setter}}(const {{{dataType}}} &{{name}});

{{/vars}}
Expand All @@ -53,6 +53,6 @@ private:
}
{{/cppNamespaceDeclarations}}

#endif /* {{classname}}_H_ */
#endif // {{classname}}_H
{{/model}}
{{/models}}
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
* Do not edit the class manually.
*/

#ifndef _OAI_OAIPetApiHandler_H_
#define _OAI_OAIPetApiHandler_H_
#ifndef OAI_OAIPetApiHandler_H
#define OAI_OAIPetApiHandler_H

#include <QObject>

Expand Down Expand Up @@ -46,4 +46,4 @@ public slots:

}

#endif // _OAI_OAIPetApiHandler_H_
#endif // OAI_OAIPetApiHandler_H
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
* Do not edit the class manually.
*/

#ifndef _OAI_OAIStoreApiHandler_H_
#define _OAI_OAIStoreApiHandler_H_
#ifndef OAI_OAIStoreApiHandler_H
#define OAI_OAIStoreApiHandler_H

#include <QObject>

Expand Down Expand Up @@ -41,4 +41,4 @@ public slots:

}

#endif // _OAI_OAIStoreApiHandler_H_
#endif // OAI_OAIStoreApiHandler_H
Loading