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

HPCC-31936 WsEcl unable to get sample request or response XML #18728

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions esp/bindings/http/platform/httpbinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1841,8 +1843,7 @@ int EspHttpBinding::getServiceWsdlOrXsd(IEspContext &context, CHttpRequest* requ
}

StringBuffer schema;
getServiceSchema(context, request, serviceQName, methodQName,
version, isWsdl, false, schema);
getServiceSchema(context, request, serviceQName, methodQName, version, isWsdl, false, schema);

response->setContent(schema.length(), schema.str());
response->setContentType(HTTP_TYPE_APPLICATION_XML_UTF8);
Expand Down Expand Up @@ -1937,7 +1938,7 @@ void EspHttpBinding::generateSampleXml(bool isRequest, IEspContext &context, CHt
content.appendf("<Error>generateSampleXml schema error: %s::%s</Error>", serv, method);
return;
}

getServiceSchema(context, request, serviceQName, methodQName, getVersion(context), false, false, schemaXml);

Owned<IXmlSchema> schema;
Expand Down
178 changes: 171 additions & 7 deletions esp/services/ws_ecl/ws_ecl_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<IPropertyTree> namespaces = createPTree();
appendSchemaNamespaces(namespaces, ctx, req, wsinfo);
Expand Down Expand Up @@ -1453,6 +1453,94 @@ bool CWsEclBinding::getSchema(StringBuffer& schema, IEspContext &ctx, CHttpReque
return true;
}

// 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 of ESDL.
bool CWsEclBinding::getSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, const char *service, const char *method,bool standalone)
{
StringBuffer serviceQName;
StringBuffer methodQName;

if (!qualifyServiceName(ctx, service, method, serviceQName, &methodQName))
return false;

const char *sqName = serviceQName.str();
const char *mqName = methodQName.str();

Owned<IPropertyTree> namespaces = createPTree();
appendSchemaNamespaces(namespaces, ctx, req, service, method);
Owned<IPropertyTreeIterator> nsiter = namespaces->getElements("namespace");

StringBuffer nstr;
generateNamespace(ctx, req, sqName, mqName, nstr);
schema.appendf("<xsd:schema elementFormDefault=\"qualified\" targetNamespace=\"%s\" ", nstr.str());
if (standalone)
schema.appendf(" xmlns:tns=\"%s\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"", nstr.str());
ForEach(*nsiter)
{
IPropertyTree &ns = nsiter->query();
schema.appendf(" xmlns:%s=\"%s\"", ns.queryProp("@nsvar"), ns.queryProp("@ns"));
}
schema.append(">\n");
ForEach(*nsiter)
{
IPropertyTree &ns = nsiter->query();
if (ns.hasProp("@import"))
schema.appendf("<xsd:import namespace=\"%s\" schemaLocation=\"%s\"/>", ns.queryProp("@ns"), ns.queryProp("@location"));
}


schema.append(
"<xsd:complexType name=\"EspException\">"
"<xsd:all>"
"<xsd:element name=\"Code\" type=\"xsd:string\" minOccurs=\"0\"/>"
"<xsd:element name=\"Audience\" type=\"xsd:string\" minOccurs=\"0\"/>"
"<xsd:element name=\"Source\" type=\"xsd:string\" minOccurs=\"0\"/>"
"<xsd:element name=\"Message\" type=\"xsd:string\" minOccurs=\"0\"/>"
"</xsd:all>"
"</xsd:complexType>\n"
"<xsd:complexType name=\"ArrayOfEspException\">"
"<xsd:sequence>"
"<xsd:element name=\"Source\" type=\"xsd:string\" minOccurs=\"0\"/>"
"<xsd:element name=\"Exception\" type=\"tns:EspException\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>"
"</xsd:sequence>"
"</xsd:complexType>\n"
"<xsd:element name=\"Exceptions\" type=\"tns:ArrayOfEspException\"/>\n"
);

if (ctx.queryOptions()&ESPCTX_WSDL_EXT)
{
schema.append(
"<xsd:complexType name=\"EspSecurityInfo\">"
"<xsd:all>"
"<xsd:element name=\"UsernameToken\" minOccurs=\"0\">"
"<xsd:complexType>"
"<xsd:all>"
"<xsd:element name=\"Username\" minOccurs=\"0\"/>"
"<xsd:element name=\"Password\" minOccurs=\"0\"/>"
"</xsd:all>"
"</xsd:complexType>"
"</xsd:element>"
"<xsd:element name=\"RealmToken\" minOccurs=\"0\">"
"<xsd:complexType>"
"<xsd:all>"
"<xsd:element name=\"Realm\" minOccurs=\"0\"/>"
"</xsd:all>"
"</xsd:complexType>"
"</xsd:element>"
"</xsd:all>"
"</xsd:complexType>"
"<xsd:element name=\"Security\" type=\"tns:EspSecurityInfo\"/>\n"
);
}

bool mda=(req->queryParameters()->getPropInt("mda")!=0);
getXsdDefinition(ctx, req, schema, sqName, mqName, mda);
schema.append("<xsd:element name=\"string\" nillable=\"true\" type=\"xsd:string\" />\n");
schema.append("</xsd:schema>");
return true;
}

int CWsEclBinding::getGenForm(IEspContext &context, CHttpRequest* request, CHttpResponse* response, WsEclWuInfo &wuinfo, bool box)
{
IConstWorkUnit *wu = wuinfo.ensureWorkUnit();
Expand Down Expand Up @@ -1513,7 +1601,7 @@ int CWsEclBinding::getGenForm(IEspContext &context, CHttpRequest* request, CHttp
}
}
else
getSchema(formxml, context, request, wuinfo);
getSimpleSchema(formxml, context, request, wuinfo);

formxml.append("<CustomViews>");
if (web)
Expand Down Expand Up @@ -1621,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<IXmlSchema> schema = createXmlSchemaFromString(schemaXml);
if (schema.get())
Expand Down Expand Up @@ -1657,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<IXmlSchema> schema = createXmlSchemaFromString(schemaXml);
if (schema.get())
Expand Down Expand Up @@ -2290,20 +2378,96 @@ 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;
}

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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
if (context.queryRequestParameters()->hasProp("display"))
content.append("<?xml-stylesheet type=\"text/xsl\" href=\"/esp/xslt/xmlformatter.xsl\"?>");
else if (isWsdl && context.queryRequestParameters()->hasProp("wsdlviewer"))
content.append("<?xml-stylesheet type=\"text/xsl\" href=\"/esp/xslt/wsdl-viewer.xsl\"?>");
if (isWsdl)
{
content.appendf("<definitions xmlns=\"http://schemas.xmlsoap.org/wsdl/\" xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" xmlns:http=\"http://schemas.xmlsoap.org/wsdl/http/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""
" xmlns:mime=\"http://schemas.xmlsoap.org/wsdl/mime/\" xmlns:tns=\"%s\""
" targetNamespace=\"%s\">", ns.str(), ns.str());
content.append("<types>");
}

getSchema(content,context,request,service,method,!isWsdl);

if (isWsdl)
{
content.append("</types>");

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("&amp;").appendf("encode_=%s", (encval && *encval) ? encval : "1");
}

content.appendf("<service name=\"%s\">", sqName);
content.appendf("<port name=\"%sServiceSoap\" binding=\"tns:%sServiceSoap\">", sqName, sqName);
content.appendf("<soap:address location=\"%s\"/>", location.str());
content.append("</port>");
content.append("</service>");
content.append("</definitions>");
}

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)
{
Expand Down Expand Up @@ -2423,7 +2587,7 @@ int CWsEclBinding::getRestURL(IEspContext *ctx, CHttpRequest *request, CHttpResp

StringBuffer schemaXml;

getSchema(schemaXml, *ctx, request, wsinfo);
getSimpleSchema(schemaXml, *ctx, request, wsinfo);
Owned<IXmlSchema> schema = createXmlSchemaFromString(schemaXml);
if (schema.get())
{
Expand Down
8 changes: 7 additions & 1 deletion esp/services/ws_ecl/ws_ecl_service.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,12 @@ class CWsEclBinding : public CHttpSoapBinding
private:
CWsEclService *wsecl;

protected:
bool getSchema(StringBuffer& schema, IEspContext &ctx, CHttpRequest* req, const char *service, const char *method,bool standalone) override;
Copy link
Contributor

Choose a reason for hiding this comment

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

Was there any specific reason this was moved to being protected from public?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function with the final bool parameter wasn't overridden in this class before, but it is/was protected in the base class EspHttpBinding- I think it just looks confusing because I renamed & moved the other one.

The other getSchema function (with the final wuinfo parameter) I moved from public to protected in this class and renamed to getSimpleSchema (on your suggestion- seemed reasonable especially now that it makes sense to refactor it away in favor of the other one).

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) :
CHttpSoapBinding(cfg, bindname, procname), wsecl(NULL)
Expand Down Expand Up @@ -199,7 +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);

Expand Down
Loading