From f5bf94d87b0ff31ea9cc111328e688e117442f0f Mon Sep 17 00:00:00 2001 From: Terrence Asselin Date: Thu, 6 Jun 2024 14:36:50 -0500 Subject: [PATCH] HPCC-31936 Fix WsEcl sample XML, WSDL and XSD features Move the implementation of EspHttpBinding::getWsdlOrXsd prior to HPCC-28978 into CWsEclBinding. Change the onXSD/onWsdl handlers in CWsEclBinding to call getWsdlOrXsd directly. Noted that the non-overridden CWsEclBinding member function getSchema was substantially similar to the overridden version, so renamed it getSimpleSchema and made it protected. Created ticket HPCC-32016 to refactor. Signed-off-by: Terrence Asselin --- esp/bindings/http/platform/httpbinding.cpp | 19 ++--- esp/services/ws_ecl/ws_ecl_service.cpp | 94 +++++++++++++++++++--- esp/services/ws_ecl/ws_ecl_service.hpp | 6 +- 3 files changed, 95 insertions(+), 24 deletions(-) diff --git a/esp/bindings/http/platform/httpbinding.cpp b/esp/bindings/http/platform/httpbinding.cpp index c557867acce..c5a9e831844 100644 --- a/esp/bindings/http/platform/httpbinding.cpp +++ b/esp/bindings/http/platform/httpbinding.cpp @@ -1764,7 +1764,9 @@ void EspHttpBinding::getServiceSchema(IEspContext& context, CHttpRequest* reque StringBuffer xmlFilename; if (!getServiceXmlFilename(xmlFilename)) { - throw MakeStringException(-1, "Unable to get service XML filename"); + // Allow subclassed specialized implementation that doesn't use ESDL + getSchema(schema, context, request, serviceQName, methodQName, true); + return; } StringBuffer nstr; @@ -1841,12 +1843,7 @@ int EspHttpBinding::getServiceWsdlOrXsd(IEspContext &context, CHttpRequest* requ } StringBuffer schema; - // Allow derived classes such as WsEcl to use custom getSchema() logic when there is no serviceXmlFilename - StringBuffer serviceXmlFilename; - if (getServiceXmlFilename(serviceXmlFilename)) - getServiceSchema(context, request, serviceQName, methodQName, version, isWsdl, false, schema); - else - getSchema(schema, context, request, service, method, true); + getServiceSchema(context, request, serviceQName, methodQName, version, isWsdl, false, schema); response->setContent(schema.length(), schema.str()); response->setContentType(HTTP_TYPE_APPLICATION_XML_UTF8); @@ -1941,12 +1938,8 @@ void EspHttpBinding::generateSampleXml(bool isRequest, IEspContext &context, CHt content.appendf("generateSampleXml schema error: %s::%s", serv, method); return; } - // Allow derived classes such as WsEcl to use custom getSchema() logic when there is no serviceXmlFilename - StringBuffer serviceXmlFilename; - if (getServiceXmlFilename(serviceXmlFilename)) - getServiceSchema(context, request, serviceQName, methodQName, getVersion(context), false, false, schemaXml); - else - getSchema(schemaXml, context, request, serv, method, true); + + getServiceSchema(context, request, serviceQName, methodQName, getVersion(context), false, false, schemaXml); Owned schema; IXmlType* type = nullptr; diff --git a/esp/services/ws_ecl/ws_ecl_service.cpp b/esp/services/ws_ecl/ws_ecl_service.cpp index 1ffa551ebf4..6856305cc8e 100644 --- a/esp/services/ws_ecl/ws_ecl_service.cpp +++ b/esp/services/ws_ecl/ws_ecl_service.cpp @@ -1403,7 +1403,7 @@ int CWsEclBinding::getXsdDefinition(IEspContext &context, CHttpRequest *request, } -bool CWsEclBinding::getSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, WsEclWuInfo &wsinfo) +bool CWsEclBinding::getSimpleSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, WsEclWuInfo &wsinfo) { Owned namespaces = createPTree(); appendSchemaNamespaces(namespaces, ctx, req, wsinfo); @@ -1453,9 +1453,9 @@ bool CWsEclBinding::getSchema(StringBuffer& schema, IEspContext &ctx, CHttpReque return true; } -// Moved from the prior implementation in EspHttpBinding which relies on ESDL to generate the schema +// Moved from the prior implementation in EspHttpBinding which now relies on ESDL to generate the schema. // However, since WsEcl is acting a front-end for roxie queries, it needs this custom implementation -// that uses the information from the roxie instead. +// that uses the information from the roxie instead of ESDL. bool CWsEclBinding::getSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, const char *service, const char *method,bool standalone) { StringBuffer serviceQName; @@ -1601,7 +1601,7 @@ int CWsEclBinding::getGenForm(IEspContext &context, CHttpRequest* request, CHttp } } else - getSchema(formxml, context, request, wuinfo); + getSimpleSchema(formxml, context, request, wuinfo); formxml.append(""); if (web) @@ -1709,7 +1709,7 @@ void CWsEclBinding::getWsEcl2XmlRequest(StringBuffer& soapmsg, IEspContext &cont element.append(wsinfo.queryname.str()).append("Request"); StringBuffer schemaXml; - getSchema(schemaXml, context, request, wsinfo); + getSimpleSchema(schemaXml, context, request, wsinfo); ESPLOG(LogMax,"request schema: %s", schemaXml.str()); Owned schema = createXmlSchemaFromString(schemaXml); if (schema.get()) @@ -1745,7 +1745,7 @@ void CWsEclBinding::getWsEclJsonRequest(StringBuffer& jsonmsg, IEspContext &cont element.append("Request"); StringBuffer schemaXml; - getSchema(schemaXml, context, request, wsinfo); + getSimpleSchema(schemaXml, context, request, wsinfo); ESPLOG(LogMax,"request schema: %s", schemaXml.str()); Owned schema = createXmlSchemaFromString(schemaXml); if (schema.get()) @@ -2378,7 +2378,7 @@ int CWsEclBinding::getWsdlBindings(IEspContext &context, CHttpRequest *request, int CWsEclBinding::onGetWsdl(IEspContext &context, CHttpRequest* request, CHttpResponse* response, WsEclWuInfo &wsinfo) { context.setBindingValue(&wsinfo); - EspHttpBinding::onGetWsdl(context, request, response, wsinfo.qsetname.str(), wsinfo.queryname.str()); + getWsdlOrXsd(context, request, response, wsinfo.qsetname.str(), wsinfo.queryname.str(), true); context.setBindingValue(NULL); return 0; } @@ -2386,12 +2386,88 @@ int CWsEclBinding::onGetWsdl(IEspContext &context, CHttpRequest* request, CHttpR int CWsEclBinding::onGetXsd(IEspContext &context, CHttpRequest* request, CHttpResponse* response, WsEclWuInfo &wsinfo) { context.setBindingValue(&wsinfo); - EspHttpBinding::onGetXsd(context, request, response, wsinfo.qsetname.str(), wsinfo.queryname.str()); + getWsdlOrXsd(context, request, response, wsinfo.qsetname.str(), wsinfo.queryname.str(), false); context.setBindingValue(NULL); return 0; } +int CWsEclBinding::getWsdlOrXsd(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method, bool isWsdl) +{ + bool mda=(request->queryParameters()->getPropInt("mda")!=0); + try + { + StringBuffer serviceQName; + StringBuffer methodQName; + + if (!qualifyServiceName(context, service, method, serviceQName, &methodQName)) + { + return onGetNotFound(context, request, response, service); + } + else + { + const char *sqName = serviceQName.str(); + const char *mqName = methodQName.str(); + StringBuffer ns; + generateNamespace(context, request, serviceQName.str(), methodQName.str(), ns); + + StringBuffer content(""); + if (context.queryRequestParameters()->hasProp("display")) + content.append(""); + else if (isWsdl && context.queryRequestParameters()->hasProp("wsdlviewer")) + content.append(""); + if (isWsdl) + { + content.appendf("", ns.str(), ns.str()); + content.append(""); + } + + getSchema(content,context,request,service,method,!isWsdl); + + if (isWsdl) + { + content.append(""); + + getWsdlMessages(context, request, content, sqName, mqName, mda); + getWsdlPorts(context, request, content, sqName, mqName, mda); + getWsdlBindings(context, request, content, sqName, mqName, mda); + + StringBuffer location(getWsdlAddress()); + if (request->queryParameters()->hasProp("wsdl_destination_path")) + location.append(request->queryParameters()->queryProp("wsdl_destination_path")); + else + location.append('/').append(sqName).appendf("?ver_=%g", context.getClientVersion()); + + if (request->queryParameters()->hasProp("encode_results")) + { + const char *encval = request->queryParameters()->queryProp("encode_results"); + location.append("&").appendf("encode_=%s", (encval && *encval) ? encval : "1"); + } + + content.appendf("", sqName); + content.appendf("", sqName, sqName); + content.appendf("", location.str()); + content.append(""); + content.append(""); + content.append(""); + } + + response->setContent(content.length(), content.str()); + response->setContentType(HTTP_TYPE_APPLICATION_XML_UTF8); + response->setStatus(HTTP_STATUS_OK); + } + } + catch (IException *e) + { + return onGetException(context, request, response, *e); + } + + response->send(); + return 0; +} + int CWsEclBinding::getWsEclDefinition(CHttpRequest* request, CHttpResponse* response, const char *thepath) { @@ -2511,7 +2587,7 @@ int CWsEclBinding::getRestURL(IEspContext *ctx, CHttpRequest *request, CHttpResp StringBuffer schemaXml; - getSchema(schemaXml, *ctx, request, wsinfo); + getSimpleSchema(schemaXml, *ctx, request, wsinfo); Owned schema = createXmlSchemaFromString(schemaXml); if (schema.get()) { diff --git a/esp/services/ws_ecl/ws_ecl_service.hpp b/esp/services/ws_ecl/ws_ecl_service.hpp index 54f422f2cf7..2a8e9edbe82 100644 --- a/esp/services/ws_ecl/ws_ecl_service.hpp +++ b/esp/services/ws_ecl/ws_ecl_service.hpp @@ -142,6 +142,9 @@ class CWsEclBinding : public CHttpSoapBinding protected: bool getSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, const char *service, const char *method,bool standalone) override; + int getWsdlOrXsd(IEspContext &context, CHttpRequest* request, CHttpResponse* response, const char *service, const char *method, bool isWsdl); + // Does not provide all the flexibility of the getSchema override. Consider refactoring out to use getSchema in its place. + bool getSimpleSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, WsEclWuInfo &wsinfo) ; public: CWsEclBinding(IPropertyTree *cfg, const char *bindname, const char *procname) : @@ -202,8 +205,7 @@ class CWsEclBinding : public CHttpSoapBinding bool qualifyServiceName(IEspContext &context, const char *servname, const char *methname, StringBuffer &servQName, StringBuffer *methQName){servQName.clear().append(servname); if (methQName) methQName->clear().append(methname); return true;} int getXsdDefinition(IEspContext &context, CHttpRequest *request, StringBuffer &content, WsEclWuInfo &wsinfo); - bool getSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, WsEclWuInfo &wsinfo) ; - + void appendSchemaNamespaces(IPropertyTree *namespaces, IEspContext &ctx, CHttpRequest* req, WsEclWuInfo &wsinfo); void appendSchemaNamespaces(IPropertyTree *namespaces, IEspContext &ctx, CHttpRequest* req, const char *service, const char *method);