Skip to content

Commit 48924eb

Browse files
authored
[dart] Improve content-type handling (#9517)
* [dart] Improve content-type handling * fixes #9334 * superseeds #9454 * use `prioritizedContentTypes` in the same way `JavaClientCodegen` does * move `application/json` to the front if it exists * don't do anything if it is multi-part or url-encoded as for this the first content-type already needs to match * log warning if an unsupported content-type is first after prioritizing * remove some unused code blocks from dio generators * Only use first prioritized content-type in dio generators * don't default to any content-type in dio-next, dio defaults itself to JSON
1 parent 1e92469 commit 48924eb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+358
-563
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractDartCodegen.java

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.openapitools.codegen.languages;
22

33
import com.google.common.collect.Lists;
4-
import com.google.common.collect.Maps;
54
import com.google.common.collect.Sets;
65
import io.swagger.v3.oas.models.Operation;
76
import io.swagger.v3.oas.models.media.ArraySchema;
@@ -29,6 +28,9 @@ public abstract class AbstractDartCodegen extends DefaultCodegen {
2928

3029
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractDartCodegen.class);
3130

31+
protected static final List<String> DEFAULT_SUPPORTED_CONTENT_TYPES = Arrays.asList(
32+
"application/json", "application/x-www-form-urlencoded", "multipart/form-data");
33+
3234
public static final String PUB_LIBRARY = "pubLibrary";
3335
public static final String PUB_NAME = "pubName";
3436
public static final String PUB_VERSION = "pubVersion";
@@ -556,6 +558,68 @@ public CodegenOperation fromOperation(String path, String httpMethod, Operation
556558
return op;
557559
}
558560

561+
@Override
562+
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
563+
super.postProcessOperationsWithModels(objs, allModels);
564+
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
565+
if (operations != null) {
566+
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
567+
for (CodegenOperation op : ops) {
568+
if (op.hasConsumes) {
569+
if (!op.formParams.isEmpty() || op.isMultipart) {
570+
// DefaultCodegen only sets this if the first consumes mediaType
571+
// is application/x-www-form-urlencoded or multipart.
572+
// Can just use the original
573+
op.prioritizedContentTypes = op.consumes;
574+
} else {
575+
// Prioritize content types by moving application/json to the front
576+
// similar to JavaCodegen
577+
op.prioritizedContentTypes = prioritizeContentTypes(op.consumes);
578+
String mediaType = op.prioritizedContentTypes.get(0).get("mediaType");
579+
if (!DEFAULT_SUPPORTED_CONTENT_TYPES.contains(mediaType)) {
580+
LOGGER.warn("The media-type '{}' for operation '{}' is not support in the Dart generators by default.", mediaType, op.path);
581+
}
582+
}
583+
}
584+
}
585+
}
586+
return objs;
587+
}
588+
589+
private List<Map<String, String>> prioritizeContentTypes(List<Map<String, String>> consumes) {
590+
if (consumes.size() <= 1) {
591+
// no need to change any order
592+
return consumes;
593+
}
594+
595+
List<Map<String, String>> prioritizedContentTypes = new ArrayList<>(consumes.size());
596+
597+
List<Map<String, String>> jsonVendorMimeTypes = new ArrayList<>(consumes.size());
598+
List<Map<String, String>> jsonMimeTypes = new ArrayList<>(consumes.size());
599+
600+
for (Map<String, String> consume : consumes) {
601+
String mediaType = consume.get("mediaType");
602+
if (isJsonVendorMimeType(mediaType)) {
603+
jsonVendorMimeTypes.add(consume);
604+
} else if (isJsonMimeType(mediaType)) {
605+
jsonMimeTypes.add(consume);
606+
} else {
607+
prioritizedContentTypes.add(consume);
608+
}
609+
}
610+
611+
prioritizedContentTypes.addAll(0, jsonMimeTypes);
612+
prioritizedContentTypes.addAll(0, jsonVendorMimeTypes);
613+
return prioritizedContentTypes;
614+
}
615+
616+
private static boolean isMultipartType(String mediaType) {
617+
if (mediaType != null) {
618+
return "multipart/form-data".equals(mediaType);
619+
}
620+
return false;
621+
}
622+
559623
@Override
560624
protected void updateEnumVarsWithExtensions(List<Map<String, Object>> enumVars, Map<String, Object> vendorExtensions, String dataType) {
561625
if (vendorExtensions != null && useEnumExtension && vendorExtensions.containsKey("x-enum-values")) {

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -264,32 +264,16 @@ private void appendCollection(StringBuilder sb, CodegenProperty property) {
264264

265265
@Override
266266
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
267-
objs = super.postProcessOperationsWithModels(objs, allModels);
267+
super.postProcessOperationsWithModels(objs, allModels);
268268
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
269269
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
270270

271271
Set<Map<String, Object>> serializers = new HashSet<>();
272272
Set<String> resultImports = new HashSet<>();
273273

274274
for (CodegenOperation op : operationList) {
275-
op.httpMethod = op.httpMethod.toLowerCase(Locale.ROOT);
276-
boolean isJson = true; //default to JSON
277-
boolean isForm = false;
278-
boolean isMultipart = false;
279-
if (op.consumes != null) {
280-
for (Map<String, String> consume : op.consumes) {
281-
if (consume.containsKey("mediaType")) {
282-
String type = consume.get("mediaType");
283-
isJson = type.equalsIgnoreCase("application/json");
284-
isForm = type.equalsIgnoreCase("application/x-www-form-urlencoded");
285-
isMultipart = type.equalsIgnoreCase("multipart/form-data");
286-
break;
287-
}
288-
}
289-
}
290-
291275
for (CodegenParameter param : op.bodyParams) {
292-
if (param.baseType != null && param.baseType.equalsIgnoreCase("Uint8List") && isMultipart) {
276+
if (param.baseType != null && param.baseType.equalsIgnoreCase("Uint8List") && op.isMultipart) {
293277
param.baseType = "MultipartFile";
294278
param.dataType = "MultipartFile";
295279
}
@@ -303,10 +287,6 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
303287
}
304288
}
305289

306-
op.vendorExtensions.put("x-is-json", isJson);
307-
op.vendorExtensions.put("x-is-form", isForm);
308-
op.vendorExtensions.put("x-is-multipart", isMultipart);
309-
310290
resultImports.addAll(rewriteImports(op.imports));
311291
if (op.getHasFormParams()) {
312292
resultImports.add("package:" + pubName + "/api_util.dart");

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioNextClientCodegen.java

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -305,32 +305,16 @@ private void appendBuiltValueCollection(StringBuilder sb, CodegenProperty proper
305305

306306
@Override
307307
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
308-
objs = super.postProcessOperationsWithModels(objs, allModels);
308+
super.postProcessOperationsWithModels(objs, allModels);
309309
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
310310
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
311311

312312
Set<Map<String, Object>> serializers = new HashSet<>();
313313
Set<String> resultImports = new HashSet<>();
314314

315315
for (CodegenOperation op : operationList) {
316-
op.httpMethod = op.httpMethod.toLowerCase(Locale.ROOT);
317-
boolean isJson = true; //default to JSON
318-
boolean isForm = false;
319-
boolean isMultipart = false;
320-
if (op.consumes != null) {
321-
for (Map<String, String> consume : op.consumes) {
322-
if (consume.containsKey("mediaType")) {
323-
String type = consume.get("mediaType");
324-
isJson = type.equalsIgnoreCase("application/json");
325-
isForm = type.equalsIgnoreCase("application/x-www-form-urlencoded");
326-
isMultipart = type.equalsIgnoreCase("multipart/form-data");
327-
break;
328-
}
329-
}
330-
}
331-
332316
for (CodegenParameter param : op.bodyParams) {
333-
if (param.baseType != null && param.baseType.equalsIgnoreCase("Uint8List") && isMultipart) {
317+
if (param.baseType != null && param.baseType.equalsIgnoreCase("Uint8List") && op.isMultipart) {
334318
param.baseType = "MultipartFile";
335319
param.dataType = "MultipartFile";
336320
}
@@ -344,10 +328,6 @@ public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> o
344328
}
345329
}
346330

347-
op.vendorExtensions.put("x-is-json", isJson);
348-
op.vendorExtensions.put("x-is-form", isForm);
349-
op.vendorExtensions.put("x-is-multipart", isMultipart);
350-
351331
resultImports.addAll(rewriteImports(op.imports));
352332
if (op.getHasFormParams()) {
353333
resultImports.add("package:" + pubName + "/src/api_util.dart");

modules/openapi-generator/src/main/resources/dart-dio/api.mustache

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ class {{classname}} {
6363
...?extra,
6464
},
6565
validateStatus: validateStatus,
66-
contentType: [{{^hasConsumes}}
67-
'application/json',{{/hasConsumes}}{{#hasConsumes}}{{#consumes}}
68-
'{{{mediaType}}}',{{/consumes}}{{/hasConsumes}}
69-
].first,
66+
contentType: '{{^hasConsumes}}application/json{{/hasConsumes}}{{#hasConsumes}}{{#prioritizedContentTypes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/prioritizedContentTypes}}{{/hasConsumes}}',
7067
cancelToken: cancelToken,
7168
onSendProgress: onSendProgress,
7269
onReceiveProgress: onReceiveProgress,

modules/openapi-generator/src/main/resources/dart/libraries/dio/api.mustache

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,8 @@ class {{classname}} {
6060
},{{/authMethods}}
6161
],{{/hasAuthMethods}}
6262
...?extra,
63-
},
64-
contentType: [{{^hasConsumes}}
65-
'application/json',{{/hasConsumes}}{{#hasConsumes}}{{#consumes}}
66-
'{{{mediaType}}}',{{/consumes}}{{/hasConsumes}}
67-
].first,
63+
},{{#hasConsumes}}
64+
contentType: '{{#prioritizedContentTypes}}{{#-first}}{{{mediaType}}}{{/-first}}{{/prioritizedContentTypes}}',{{/hasConsumes}}
6865
validateStatus: validateStatus,
6966
);
7067

modules/openapi-generator/src/main/resources/dart2/api.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class {{{classname}}} {
9595
{{/headerParams}}
9696
{{/hasHeaderParams}}
9797

98-
final contentTypes = <String>[{{#consumes}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/consumes}}];
98+
final contentTypes = <String>[{{#prioritizedContentTypes}}'{{{mediaType}}}'{{^-last}}, {{/-last}}{{/prioritizedContentTypes}}];
9999
final nullableContentType = contentTypes.isNotEmpty ? contentTypes[0] : null;
100100
final authNames = <String>[{{#authMethods}}'{{{name}}}'{{^-last}}, {{/-last}}{{/authMethods}}];
101101

0 commit comments

Comments
 (0)