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

openapi: add Application/XML support for request bodies #5751

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions addOns/openapi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Added
- Allow to import the OpenAPI definitions with a user (Issue 7739).
- Honour context exclusions when importing (Issue 8021).
- Application/XML support for request bodies (Issue 6767).

### Fixed
- Allow to select the contexts of the Automation Framework plan when configuring the job.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import io.swagger.v3.oas.models.parameters.RequestBody;
import java.util.List;
import java.util.Map;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.network.HttpHeaderField;
import org.zaproxy.zap.extension.openapi.generators.Generators;
import org.zaproxy.zap.extension.openapi.generators.HeadersGenerator;
Expand Down Expand Up @@ -85,13 +84,9 @@ private String generateBody() {
return generators.getBodyGenerator().generateMultiPart(schema, encoding);
}

if (content.containsKey(CONTENT_APPLICATION_XML)) {
generators.addErrorMessage(
Constant.messages.getString(
"openapi.unsupportedcontent",
operation.getOperationId(),
CONTENT_APPLICATION_XML));
return "";
if (content.containsKey("application/xml")) {
schema = content.get("application/xml").getSchema();
return generators.getBodyGenerator().generateXml(schema);
}

if (!content.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,44 @@ public String generateMultiPart(Schema<?> schema, Map<String, Encoding> encoding
return "";
}

@SuppressWarnings("rawtypes")
public String generateXml(Schema<?> schema) {
if (schema == null) {
return "";
}

StringBuilder xml = new StringBuilder();
String elementName = null;
generateXmlElements(schema, xml);
return xml.toString();
}

@SuppressWarnings("rawtypes")
private void generateXmlElements(Schema<?> schema, StringBuilder xml) {
for (Map.Entry<String, Schema> property : schema.getProperties().entrySet()) {
String elementName = property.getKey();
xml.append("<");
xml.append(elementName);
xml.append(">");

if (property.getValue().getProperties() != null) {
generateXmlElements(property.getValue(), xml);
} else {
String value = dataGenerator.generateValue(elementName, property.getValue(), false);
if ("string".equalsIgnoreCase(property.getValue().getType())
&& value.startsWith("\"")
&& value.endsWith("\"")) {
value = value.substring(1, value.length() - 1); // Remove surrounding quotes
}
xml.append(value);
}

xml.append("</");
xml.append(elementName);
xml.append(">\n");
}
}

private static String getPropertyContentType(Schema<?> schema) {
String type;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
<BODY>
<H1>OpenAPI Support</H1>
This add-on allows you to spider and import OpenAPI (Swagger) definitions, versions 1.2, 2.0, and 3.0.
<br>
<strong>Note:</strong> Generation of XML content is currently not supported.
<br><br>
The add-on will automatically detect any OpenAPI definitions and spider them as long as they are in scope.
<br><br>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
*/
package org.zaproxy.zap.extension.openapi.v3;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.emptyString;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -716,19 +712,30 @@ void shouldGenerateBodyWithNoSchema() throws IOException {
}

@Test
void shouldNotGenerateContentForApplicationXml() throws IOException {
void shouldGenerateXmlObject() throws IOException {
// Given
OpenAPI definition = parseResource("openapi_xml_bodies.yaml");
OperationModel operationModel =
new OperationModel("/xml", definition.getPaths().get("/xml").getPost(), null);
OpenAPI openAPI = parseResource("openapi_xml_bodies.yaml");

// When
String content = new RequestModelConverter().convert(operationModel, generators).getBody();
String xmlString =
generators
.getBodyGenerator()
.generateXml(
openAPI.getPaths()
.get("/xml")
.getPost()
.getRequestBody()
.getContent()
.get("application/xml")
.getSchema());

// Then
assertThat(content, is(emptyString()));
assertThat(
generators.getErrorMessages(),
contains(
"Not generating request body for operation xml, the content type application/xml is not supported."));
String expectedOutput =
"<value-string>John Doe</value-string>\n"
+ "<value-boolean>true</value-boolean>\n"
+ "<value-integer>10</value-integer>\n";

assertEquals(expectedOutput, xmlString);
}

@Test
Expand Down