Skip to content

Commit 93acbd6

Browse files
committed
fix(soap): sets namespace of RPC root response element from WSDL target namespace.
1 parent ee157b0 commit 93acbd6

File tree

6 files changed

+31
-11
lines changed

6 files changed

+31
-11
lines changed

mock/soap/src/main/java/io/gatehill/imposter/plugin/soap/SoapPluginImpl.kt

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import io.gatehill.imposter.plugin.soap.model.ParsedRawBody
5959
import io.gatehill.imposter.plugin.soap.model.ParsedSoapMessage
6060
import io.gatehill.imposter.plugin.soap.model.WsdlBinding
6161
import io.gatehill.imposter.plugin.soap.model.WsdlOperation
62+
import io.gatehill.imposter.plugin.soap.model.WsdlService
6263
import io.gatehill.imposter.plugin.soap.parser.VersionAwareWsdlParser
6364
import io.gatehill.imposter.plugin.soap.parser.WsdlParser
6465
import io.gatehill.imposter.plugin.soap.service.SoapExampleService
@@ -130,7 +131,7 @@ class SoapPluginImpl @Inject constructor(
130131

131132
when (binding.type) {
132133
BindingType.SOAP, BindingType.HTTP -> {
133-
handleBindingOperations(router, config, wsdlParser, path, binding)
134+
handleBindingOperations(router, config, wsdlParser, path, service, binding)
134135
}
135136

136137
else -> LOGGER.debug("Ignoring unsupported binding: ${binding.name}")
@@ -154,6 +155,7 @@ class SoapPluginImpl @Inject constructor(
154155
config: SoapPluginConfig,
155156
parser: WsdlParser,
156157
path: String,
158+
service: WsdlService,
157159
binding: WsdlBinding,
158160
) {
159161
val fullPath = (config.path ?: "") + path
@@ -191,7 +193,7 @@ class SoapPluginImpl @Inject constructor(
191193
}
192194

193195
LOGGER.debug("Matched operation: ${operation.name} in binding ${binding.name}")
194-
return@build handle(config, parser, binding, operation, httpExchange, bodyHolder, soapAction)
196+
return@build handle(config, parser, service, binding, operation, httpExchange, bodyHolder, soapAction)
195197
}
196198
)
197199
}
@@ -210,6 +212,7 @@ class SoapPluginImpl @Inject constructor(
210212
private fun handle(
211213
pluginConfig: SoapPluginConfig,
212214
parser: WsdlParser,
215+
service: WsdlService,
213216
binding: WsdlBinding,
214217
operation: WsdlOperation,
215218
httpExchange: HttpExchange,
@@ -226,7 +229,7 @@ class SoapPluginImpl @Inject constructor(
226229
.setStatusCode(responseBehaviour.statusCode)
227230

228231
operation.outputRef?.let {
229-
LOGGER.trace("Using output schema type: ${operation.outputRef}")
232+
LOGGER.trace("Using output schema type: {}", operation.outputRef)
230233

231234
if (!responseBehaviour.responseHeaders.containsKey(HttpUtil.CONTENT_TYPE)) {
232235
responseBehaviour.responseHeaders[HttpUtil.CONTENT_TYPE] = when (bodyHolder) {
@@ -246,6 +249,7 @@ class SoapPluginImpl @Inject constructor(
246249
httpExchange,
247250
parser.schemas,
248251
wsdlDir,
252+
service,
249253
operation.outputRef,
250254
bodyHolder
251255
)

mock/soap/src/main/java/io/gatehill/imposter/plugin/soap/model/WsdlModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import java.net.URI
4747

4848
data class WsdlService(
4949
val name: String,
50+
val targetNamespace: String?,
5051
val endpoints: List<WsdlEndpoint>,
5152
)
5253

mock/soap/src/main/java/io/gatehill/imposter/plugin/soap/parser/Wsdl1Parser.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,15 @@ class Wsdl1Parser(
7777

7878
override val services: List<WsdlService>
7979
get() {
80+
val tns = selectSingleNode(document, "/wsdl:definitions")
81+
?.getAttribute("targetNamespace")?.value
82+
8083
val services = selectNodes(document, "/wsdl:definitions/wsdl:service")
8184

8285
return services.map { element ->
8386
WsdlService(
8487
name = element.getAttributeValue("name"),
88+
targetNamespace = tns,
8589
endpoints = getPorts(element),
8690
)
8791
}

mock/soap/src/main/java/io/gatehill/imposter/plugin/soap/parser/Wsdl2Parser.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,15 @@ class Wsdl2Parser(
7474

7575
override val services: List<WsdlService>
7676
get() {
77+
val tns = selectSingleNode(document, "/wsdl:description")
78+
?.getAttribute("targetNamespace")?.value
79+
7780
val services = selectNodes(document, "/wsdl:description/wsdl:service")
7881

7982
return services.map { element ->
8083
WsdlService(
8184
name = element.getAttributeValue("name"),
85+
targetNamespace = tns,
8286
endpoints = getEndpoints(element),
8387
)
8488
}

mock/soap/src/main/java/io/gatehill/imposter/plugin/soap/service/SoapExampleService.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import io.gatehill.imposter.plugin.soap.model.OperationMessage
5050
import io.gatehill.imposter.plugin.soap.model.ParsedRawBody
5151
import io.gatehill.imposter.plugin.soap.model.ParsedSoapMessage
5252
import io.gatehill.imposter.plugin.soap.model.TypeOperationMessage
53+
import io.gatehill.imposter.plugin.soap.model.WsdlService
5354
import io.gatehill.imposter.plugin.soap.parser.WsdlRelativeXsdEntityResolver
5455
import io.gatehill.imposter.plugin.soap.util.SchemaGenerator
5556
import io.gatehill.imposter.plugin.soap.util.SoapUtil
@@ -80,18 +81,20 @@ class SoapExampleService {
8081
httpExchange: HttpExchange,
8182
schemas: Array<SchemaDocument>,
8283
wsdlDir: File,
84+
service: WsdlService,
8385
outputMessage: OperationMessage,
8486
bodyHolder: MessageBodyHolder,
8587
): Boolean {
8688
logger.debug("Generating example for {}", outputMessage)
87-
val example = generateInstanceFromSchemas(schemas, wsdlDir, outputMessage)
89+
val example = generateInstanceFromSchemas(schemas, wsdlDir, service, outputMessage)
8890
transmitExample(httpExchange, example, bodyHolder)
8991
return true
9092
}
9193

9294
private fun generateInstanceFromSchemas(
9395
schemas: Array<SchemaDocument>,
9496
wsdlDir: File,
97+
service: WsdlService,
9598
message: OperationMessage,
9699
): String {
97100
when (message) {
@@ -108,11 +111,12 @@ class SoapExampleService {
108111

109112
is TypeOperationMessage -> {
110113
// by convention, the suffix 'Response' is added to the operation name
111-
val rootElement = QName(
112-
message.typeName.namespaceURI,
113-
message.operationName + "Response",
114-
"tns"
115-
)
114+
val elementName = message.operationName + "Response"
115+
val rootElement = if (service.targetNamespace?.isNotBlank() == true) {
116+
QName(service.targetNamespace, elementName, "tns")
117+
} else {
118+
QName(elementName)
119+
}
116120

117121
val parts = mutableMapOf<String, QName>()
118122
parts[message.partName] = message.typeName
@@ -126,7 +130,8 @@ class SoapExampleService {
126130
return SampleXmlUtil.createSampleForType(elem)
127131
}
128132

129-
else -> throw UnsupportedOperationException("Unsupported output message parts: ${message::class.java.canonicalName}")
133+
// TODO support CompositeOperationMessage
134+
else -> throw UnsupportedOperationException("Unsupported output message: ${message::class.java.canonicalName}")
130135
}
131136
}
132137

mock/soap/src/main/java/io/gatehill/imposter/plugin/soap/util/SchemaGenerator.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ object SchemaGenerator {
5656

5757
fun createElementSchema(rootElement: QName, parts: Map<String, QName>): SchemaDocument {
5858
val namespaces = mutableMapOf<String, String>()
59-
namespaces[rootElement.prefix] = rootElement.namespaceURI
59+
if (rootElement.namespaceURI?.isNotBlank() == true) {
60+
namespaces[rootElement.prefix] = rootElement.namespaceURI
61+
}
6062
namespaces += parts.values.associate { it.prefix to it.namespaceURI }
6163

6264
val namespacesXml = namespaces.entries.joinToString(separator = "\n") { (prefix, nsUri) ->

0 commit comments

Comments
 (0)