Skip to content

Commit

Permalink
Apply style and explode values from encoding for form-encoded request…
Browse files Browse the repository at this point in the history
… body parameters
  • Loading branch information
harmony7 committed Apr 18, 2022
1 parent 6a77660 commit 4416b22
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1925,16 +1925,49 @@ public void setParameterExampleValue(CodegenParameter codegenParameter, RequestB
}

/**
* Sets the content type of the parameter based on the encoding specified in the request body.
* Sets the content type, style, and explode of the parameter based on the encoding specified
* in the request body.
*
* @param codegenParameter Codegen parameter
* @param mediaType MediaType from the request body
*/
public void setParameterContentType(CodegenParameter codegenParameter, MediaType mediaType) {
public void setParameterEncodingValues(CodegenParameter codegenParameter, MediaType mediaType) {
if (mediaType != null && mediaType.getEncoding() != null) {
Encoding encoding = mediaType.getEncoding().get(codegenParameter.baseName);
if (encoding != null) {
codegenParameter.contentType = encoding.getContentType();
boolean styleGiven = true;
Encoding.StyleEnum style = encoding.getStyle();
if(style == null || style == Encoding.StyleEnum.FORM) {
// (Unfortunately, swagger-parser-v3 will always provide 'form'
// when style is not specified, so we can't detect that)
style = Encoding.StyleEnum.FORM;
styleGiven = false;
}
boolean explodeGiven = true;
Boolean explode = encoding.getExplode();
if(explode == null) {
explode = style == Encoding.StyleEnum.FORM; // Default to True when form, False otherwise
explodeGiven = false;
}

if(!styleGiven && !explodeGiven) {
// Ignore contentType if style or explode are specified.
codegenParameter.contentType = encoding.getContentType();
}

codegenParameter.style = style.toString();
codegenParameter.isDeepObject = Encoding.StyleEnum.DEEP_OBJECT == style;

if(codegenParameter.isContainer) {
codegenParameter.isExplode = explode;
String collectionFormat = getCollectionFormat(codegenParameter);
codegenParameter.collectionFormat = StringUtils.isEmpty(collectionFormat) ? "csv" : collectionFormat;
codegenParameter.isCollectionFormatMulti = "multi".equals(collectionFormat);
} else {
codegenParameter.isExplode = false;
codegenParameter.collectionFormat = null;
codegenParameter.isCollectionFormatMulti = false;
}
} else {
LOGGER.debug("encoding not specified for {}", codegenParameter.baseName);
}
Expand Down Expand Up @@ -4080,7 +4113,7 @@ public CodegenOperation fromOperation(String path,
formParams = fromRequestBodyToFormParameters(requestBody, imports);
op.isMultipart = contentType.startsWith("multipart");
for (CodegenParameter cp : formParams) {
setParameterContentType(cp, requestBody.getContent().get(contentType));
setParameterEncodingValues(cp, requestBody.getContent().get(contentType));
postProcessParameter(cp);
}
// add form parameters to the beginning of all parameter list
Expand Down Expand Up @@ -6391,11 +6424,12 @@ public CodegenParameter fromFormProperty(String name, Schema propertySchema, Set
LOGGER.warn("Could not compute datatypeWithEnum from {}, {}", arrayInnerProperty.baseType, arrayInnerProperty.enumName);
}
// end of hoisting
//TODO fix collectionFormat for form parameters
//collectionFormat = getCollectionFormat(s);

// collectionFormat for form parameter does not consider
// style and explode from encoding at this point
String collectionFormat = getCollectionFormat(codegenParameter);
// default to csv:
codegenParameter.collectionFormat = StringUtils.isEmpty(collectionFormat) ? "csv" : collectionFormat;
codegenParameter.isCollectionFormatMulti = "multi".equals(collectionFormat);

// recursively add import
while (arrayInnerProperty != null) {
Expand Down Expand Up @@ -6437,8 +6471,6 @@ public CodegenParameter fromFormProperty(String name, Schema propertySchema, Set
// set nullable
setParameterNullable(codegenParameter, codegenProperty);

//TODO collectionFormat for form parameter not yet supported
//codegenParameter.collectionFormat = getCollectionFormat(propertySchema);
return codegenParameter;
}

Expand Down Expand Up @@ -7360,14 +7392,30 @@ protected static boolean isJsonVendorMimeType(String mime) {
}

/**
* Returns null by default but can be overwritten to return a valid collectionFormat
* Builds OAPI 2.0 collectionFormat value based on style and explode values
* for the {@link CodegenParameter}.
*
* @param codegenParameter parameter
* @return string for a collectionFormat.
*/
protected String getCollectionFormat(CodegenParameter codegenParameter) {
return null;
if ("form".equals(codegenParameter.style)) {
// Ref: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#style-values
if (codegenParameter.isExplode) {
return "multi";
} else {
return "csv";
}
} else if ("simple".equals(codegenParameter.style)) {
return "csv";
} else if ("pipeDelimited".equals(codegenParameter.style)) {
return "pipes";
} else if ("spaceDelimited".equals(codegenParameter.style)) {
return "ssv";
} else {
// Doesn't map to any of the collectionFormat strings
return null;
}
}

private CodegenComposedSchemas getComposedSchemas(Schema schema) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4049,6 +4049,44 @@ public void testRequestBodyContent() {
cp = mt.getSchema();
assertEquals(cp.baseName, "SchemaForRequestBodyTextPlain");
assertTrue(cp.isString);

path = "/requestBodyWithEncodingTypes";
co = codegen.fromOperation(path, "POST", openAPI.getPaths().get(path).getPost(), null);
List<CodegenParameter> formParams = co.formParams;

assertEquals(formParams.get(0).paramName, "intParam");
assertFalse(formParams.get(0).isContainer);
assertFalse(formParams.get(0).isExplode); // Should not be true for non-container

assertEquals(formParams.get(1).paramName, "explodeTrue");
assertTrue(formParams.get(1).isContainer);
assertEquals(formParams.get(1).style, Encoding.StyleEnum.FORM.toString());
assertTrue(formParams.get(1).isExplode);
assertNull(formParams.get(1).contentType);

assertEquals(formParams.get(2).paramName, "explodeFalse");
assertTrue(formParams.get(2).isContainer);
assertEquals(formParams.get(2).style, Encoding.StyleEnum.FORM.toString());
assertFalse(formParams.get(2).isExplode);
assertNull(formParams.get(2).contentType);

assertEquals(formParams.get(3).paramName, "noStyleNoExplode");
assertTrue(formParams.get(3).isContainer);
assertEquals(formParams.get(3).style, Encoding.StyleEnum.FORM.toString());
assertTrue(formParams.get(3).isExplode); // Defaults to true for style == FORM
assertEquals(formParams.get(3).contentType, "text/plain");

assertEquals(formParams.get(4).paramName, "styleSpecified");
assertTrue(formParams.get(4).isContainer);
assertEquals(formParams.get(4).style, Encoding.StyleEnum.SPACE_DELIMITED.toString());
assertFalse(formParams.get(4).isExplode);
assertNull(formParams.get(4).contentType);

assertEquals(formParams.get(5).paramName, "styleSpecifiedNoExplode");
assertTrue(formParams.get(5).isContainer);
assertEquals(formParams.get(5).style, Encoding.StyleEnum.SPACE_DELIMITED.toString());
assertFalse(formParams.get(5).isExplode); // Defaults to false for style other than FORM
assertNull(formParams.get(5).contentType);
}

@Test
Expand Down
51 changes: 51 additions & 0 deletions modules/openapi-generator/src/test/resources/3_0/content-data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,57 @@ paths:
responses:
200:
description: OK
/requestBodyWithEncodingTypes:
post:
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
int-param:
type: integer
explode-true:
type: array
items:
type: string
explode-false:
type: array
items:
type: string
no-style-no-explode:
type: array
items:
type: string
style-specified:
type: array
items:
type: string
style-specified-no-explode:
type: array
items:
type: string
encoding:
int-param:
explode: true # should be disregarded for non-container
explode-true:
contentType: text/plain # should be disregarded
explode: true
explode-false:
contentType: text/plain # should be disregarded
explode: false
no-style-no-explode:
contentType: text/plain
style-specified:
contentType: text/plain # should be disregarded
style: spaceDelimited
explode: false
style-specified-no-explode:
contentType: text/plain # should be disregarded
style: spaceDelimited
responses:
200:
description: OK
components:
headers:
X-Rate-Limit:
Expand Down

0 comments on commit 4416b22

Please sign in to comment.