Skip to content

Commit b50fc57

Browse files
committed
Add REMOVE_FILTER cookies, headers and queryParams
1 parent f0f0d7c commit b50fc57

4 files changed

Lines changed: 607 additions & 35 deletions

File tree

docs/customization.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -739,9 +739,9 @@ The `REMOVE_FILTER` parameter allows the removal of elements in an openAPI docum
739739
- **`deprecated`**
740740
When specified as `deprecated` or set to `deprecated:true`, all operations, schemas, properties and parameters marked with `deprecated: true` are removed.
741741

742-
- **`removeTags`**
742+
- **`removeTags`**
743743
When specified as `removeTags` or set to `removeTags:true`, all tags are removed from the operations.
744-
When set to `removeTags:store|user` all tags whose name is `store` or `user` are removed.
744+
When set to `removeTags:store|user` all tags named is `store` or `user` are removed.
745745
When set to `removeTags:keepOnlyFirstTag` perform the KEEP_ONLY_FIRST_TAG_IN_OPERATION normalization
746746

747747
- **`removeVendorExtensions`**
@@ -750,11 +750,22 @@ The `REMOVE_FILTER` parameter allows the removal of elements in an openAPI docum
750750

751751
- **`x-`**
752752
When specified as `x-role`, remove operations, schemas, properties and parameters having a vendor extension `x-role`.
753-
When set to `x-role:admin|superuser`, remove operations, schemas, properties and parameters marked with vendorExtension `x-role:admin` or `x-role:superuser`.
753+
When set to `x-role:admin|superuser`, remove operations, schemas, properties and parameters marked with vendorExtension `x-role: admin` or `x-role: superuser`.
754754

755755
- **`tags`**
756756
When set as `tags:user|store`, remove operations marked with tags: user or store.
757757

758+
- **`headers`**
759+
When set as `headers`, remove all headers.
760+
When set as `headers:x-api-key`, remove header parameters named `x-api-key`.
761+
762+
- **`cookies`**
763+
When set as `cookies`, remove all cookies.
764+
When set as `cookies:x-api-key`, remove cookie parameters named `x-api-key`.
765+
766+
- **`queryParams`**
767+
When set as `queryParams:offset|limit`, remove request parameters named `offset` or `limit`.`.
768+
758769
- **`unused`**
759770
When specified as `unused` or set to `unused:true`, remove all unused schemas, tags, requestBodies, responses and parameters.
760771
Optionally set individual options like in `unused:schemas|tags|requestBodies|responses|parameters`

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

Lines changed: 108 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ protected void processRemoveItems() {
436436
}
437437
processRemoveEmptyPath();
438438
processRemoveUnusedRequestBodies();
439+
processRemoveEmptyResponseHeaders();
439440
processRemoveUnusedResponses();
440441
processRemoveUnusedParameters();
441442
processRemoveSchemas();
@@ -486,9 +487,25 @@ protected void processRemoveUnusedRequestBodies() {
486487
}
487488
}
488489

490+
protected void processRemoveEmptyResponseHeaders() {
491+
if (openAPI.getComponents() != null && openAPI.getComponents().getResponses() != null) {
492+
openAPI.getComponents().getResponses()
493+
.forEach((key, value) -> processEmptyResponseHeaders(value));
494+
}
495+
if (openAPI.getPaths()!= null) {
496+
openAPI.getPaths().values().stream()
497+
.flatMap(pathItem -> pathItem.readOperations().stream())
498+
.map(Operation::getResponses)
499+
.filter(Objects::nonNull)
500+
.map(ApiResponses::values)
501+
.flatMap(responses -> responses.stream())
502+
.forEach(this::processEmptyResponseHeaders);
503+
}
504+
}
505+
489506
protected void processRemoveUnusedResponses() {
490507
if (removeFilter.unusedResponses) {
491-
if (openAPI.getComponents() != null && openAPI.getComponents().getResponses() != null) {
508+
if (openAPI.getComponents() != null && openAPI.getComponents().getResponses() != null && openAPI.getPaths() != null) {
492509
Set<String> unusedResponses = openAPI.getPaths().values().stream()
493510
.flatMap(pathItem -> pathItem.readOperations().stream())
494511
.map(Operation::getResponses)
@@ -509,6 +526,12 @@ protected void processRemoveUnusedResponses() {
509526
}
510527
}
511528

529+
protected void processEmptyResponseHeaders(ApiResponse response) {
530+
if (response.getHeaders() != null && response.getHeaders().isEmpty()) {
531+
response.setHeaders(null);
532+
}
533+
}
534+
512535
protected void processRemoveUnusedParameters() {
513536
if (removeFilter.unusedParameters) {
514537
if (openAPI.getComponents() != null && openAPI.getComponents().getParameters() != null) {
@@ -790,6 +813,14 @@ protected void normalizeHeaders(Map<String, Header> headers) {
790813
return;
791814
}
792815

816+
if (removeFilter.hasFilter()) {
817+
Set<String> headersToRemove = headers.entrySet().stream()
818+
.filter(entry -> removeFilter.matchHeader(entry.getKey(), ModelUtils.getReferencedHeader(openAPI, entry.getValue())))
819+
.map(Map.Entry::getKey)
820+
.collect(Collectors.toSet());
821+
headers.keySet().removeIf(key -> headersToRemove.contains(key));
822+
}
823+
793824
for (String headerKey : headers.keySet()) {
794825
Header h = headers.get(headerKey);
795826
Schema updatedHeader = normalizeSchema(h.getSchema(), new HashSet<>());
@@ -2232,19 +2263,28 @@ public void applyParameter(String path, PathItem pathItem, PathItem.HttpMethod m
22322263
return;
22332264
}
22342265
if (operation != null) {
2235-
if (!matchExtension(parameterExtensions)) {
2266+
if (!matchParameterExtension(path, method, operation, parameter)) {
22362267
parameter.addExtension(X_INTERNAL, true);
22372268
String operationInfo = getOperationInfo(path, pathItem, method, operation);
2238-
getLogger().info("Parameter `{}` in `{}` marked as internal (x-internal: true) by the {} FILTER", parameter.getName(), operationInfo, this.vendorExtensions);
2269+
getLogger().info("Parameter `{}` in `{}` marked as internal (x-internal: true) by FILTER", parameter.getName(), operationInfo);
22392270
}
22402271
} else {
2241-
if (!matchExtension(parameterExtensions)) {
2272+
if (!matchParameterExtension(path, parameter)) {
22422273
parameter.addExtension(X_INTERNAL, true);
2243-
getLogger().info("Parameter `{}` in `{}` marked as internal (x-internal: true) by the {} FILTER", parameter.getName(), path, this.vendorExtensions);
2274+
getLogger().info("Parameter `{}` in `{}` marked as internal (x-internal: true) by FILTER", parameter.getName(), path);
22442275
}
22452276
}
22462277
}
22472278

2279+
protected boolean matchParameterExtension(String path, PathItem.HttpMethod method, Operation operation, Parameter parameter) {
2280+
return matchExtension(parameter.getExtensions());
2281+
}
2282+
2283+
protected boolean matchParameterExtension(String path, Parameter parameter) {
2284+
return matchExtension(parameter.getExtensions());
2285+
}
2286+
2287+
22482288
protected boolean logIfMatch(Object filterName, String operation, boolean filterMatched) {
22492289
if (filterMatched) {
22502290
logIfMatch(filterName, operation);
@@ -2253,7 +2293,7 @@ protected boolean logIfMatch(Object filterName, String operation, boolean filter
22532293
}
22542294

22552295
protected void logMismatch(String operation) {
2256-
getLogger().info("operation `{}` marked as internal only (x-internal: true) by FILTER", operation);
2296+
getLogger().debug("operation `{}` marked as internal only (x-internal: true) by FILTER", operation);
22572297
}
22582298

22592299

@@ -2318,7 +2358,16 @@ protected void processNormalizeOtherThanObjectWithProperties(Schema schema) {
23182358
}
23192359

23202360
public static class RemoveFilter {
2321-
private final static Set<String> ANYSET = new HashSet<>();
2361+
private final static Set<String> ANYSET = Collections.singleton("any");
2362+
public static final String REMOVE_TAGS = "removeTags";
2363+
public static final String REMOVE_VENDOR_EXTENSIONS = "removeVendorExtensions";
2364+
public static final String DEPRECATED = "deprecated";
2365+
public static final String UNUSED = "unused";
2366+
public static final String TAGS = "tags";
2367+
public static final String INTERNAL = "internal";
2368+
public static final String HEADERS = "headers";
2369+
private static final String QUERYPARAMS = "queryParams";
2370+
private static final String COOKIES = "cookies";
23222371
private final String filters;
23232372
private boolean hasFilter;
23242373

@@ -2338,6 +2387,9 @@ public static class RemoveFilter {
23382387

23392388
protected boolean keepOnlyFirstTagInOperation;
23402389
protected Set<String> removeTags = Collections.emptySet();
2390+
protected Set<String> headers = Collections.emptySet();
2391+
protected Set<String> cookies = Collections.emptySet();
2392+
protected Set<String> queryParams = Collections.emptySet();
23412393
protected boolean deprecated;
23422394
protected Set<String> tags = Collections.emptySet();
23432395
protected Map<String, Set<String>> vendorExtensions = new HashMap<>();
@@ -2363,7 +2415,7 @@ public boolean parse() {
23632415
doParse();
23642416
return hasFilter();
23652417
} catch (RuntimeException e) {
2366-
String message = String.format(Locale.ROOT, "FILTER rule [%s] `. Error: %s",
2418+
String message = String.format(Locale.ROOT, "REMOVE_FILTER rule [%s] `. Error: %s",
23672419
filters, e.getMessage());
23682420
throw new IllegalArgumentException(message);
23692421
}
@@ -2384,7 +2436,6 @@ private void doParse() {
23842436
String filterKey = filterStrs[0].trim();
23852437
String filterValue;
23862438
if (isAny) {
2387-
filterStrs = new String[] { filterStrs[0], "true" };
23882439
isTrue = true;
23892440
isBoolean = true;
23902441
set = Collections.emptySet();
@@ -2395,9 +2446,11 @@ private void doParse() {
23952446
isTrue = Boolean.parseBoolean(filterValue);
23962447
isBoolean = "false".equals(filterValue) || isTrue;
23972448
}
2449+
2450+
Set<String> anyOrSet = isAny? getAnySet(isTrue): set;
23982451
hasFilter = true;
23992452

2400-
if ("internal".equals(filterKey)) {
2453+
if (INTERNAL.equals(filterKey)) {
24012454
if (isBoolean) {
24022455
internalOperations = isTrue;
24032456
internalSchemas = isTrue;
@@ -2409,9 +2462,9 @@ private void doParse() {
24092462
internalProperties = set.contains("properties");
24102463
internalParameters = set.contains("parameters");
24112464
}
2412-
} else if ("deprecated".equals(filterKey)) {
2465+
} else if (DEPRECATED.equals(filterKey)) {
24132466
this.deprecated = isTrue;
2414-
} else if ("unused".equals(filterKey)) {
2467+
} else if (UNUSED.equals(filterKey)) {
24152468
if (isBoolean) {
24162469
unusedSchemas = isTrue;
24172470
unusedTags = isTrue;
@@ -2420,34 +2473,34 @@ private void doParse() {
24202473
unusedParameters = isTrue;
24212474
} else {
24222475
unusedSchemas = set.contains("schemas");
2423-
unusedTags = set.contains("tags");
2476+
unusedTags = set.contains(TAGS);
24242477
unusedRequestBodies = set.contains("requestBodies");
24252478
unusedResponses = set.contains("responses");
24262479
unusedParameters = set.contains("parameters");
24272480
}
24282481
} else if (REMOVE_X_INTERNAL.equals(filterKey)) {
24292482
removeXInternal = isTrue;
2430-
} else if ("removeVendorExtensions".equals(filterKey)) {
2483+
} else if (REMOVE_VENDOR_EXTENSIONS.equals(filterKey)) {
24312484
if (isAny) {
24322485
removeXInternal = isTrue;
2433-
removeExtensions = getAnySet(isTrue);
2434-
} else {
2435-
removeExtensions = set;
24362486
}
2487+
removeExtensions = anyOrSet;
24372488
} else if (KEEP_ONLY_FIRST_TAG_IN_OPERATION.equals(filterKey)) {
24382489
keepOnlyFirstTagInOperation = isTrue;
2439-
} else if ("removeTags".equals(filterKey)) {
2490+
} else if (REMOVE_TAGS.equals(filterKey)) {
24402491
if ("keepOnlyFirstTag".equals(filterValue)) {
24412492
keepOnlyFirstTagInOperation = true;
24422493
} else {
2443-
if (isAny) {
2444-
removeTags = getAnySet(isTrue);
2445-
} else {
2446-
removeTags = set;
2447-
}
2494+
removeTags = anyOrSet;
24482495
}
2449-
} else if ("tags".equals(filterKey)) {
2496+
} else if (TAGS.equals(filterKey)) {
24502497
tags = set;
2498+
} else if (HEADERS.equals(filterKey)) {
2499+
headers = anyOrSet;
2500+
} else if (QUERYPARAMS.equals(filterKey)) {
2501+
queryParams = anyOrSet;
2502+
} else if (COOKIES.equals(filterKey)) {
2503+
cookies = anyOrSet;
24512504
} else if (filterKey.startsWith("x-")) {
24522505
vendorExtensions.put(filterKey, isAny ? getAnySet(isTrue) : set);
24532506
} else {
@@ -2647,10 +2700,39 @@ protected boolean matchParameter(Parameter parameter) {
26472700
if (deprecated && Boolean.TRUE.equals(parameter.getDeprecated())) {
26482701
return true;
26492702
}
2703+
String in = parameter.getIn();
2704+
if ("query".equals(in) && matchParameter(parameter, this.queryParams)) {
2705+
return true;
2706+
}
2707+
if ("cookie".equals(in) && matchParameter(parameter, this.cookies)) {
2708+
return true;
2709+
}
2710+
if ("header".equals(in) && matchParameter(parameter, this.headers)) {
2711+
return true;
2712+
}
26502713

26512714
return matchExtension(parameter.getExtensions());
26522715
}
26532716

2717+
private boolean matchParameter(Parameter parameter, Set<String> params) {
2718+
return matchValue(parameter.getName(), params);
2719+
}
2720+
2721+
private boolean matchValue(Object value, Set<String> valuesToMatch) {
2722+
if (isEmpty(valuesToMatch)) {
2723+
return false;
2724+
}
2725+
if (valuesToMatch == ANYSET) {
2726+
return true;
2727+
}
2728+
return valuesToMatch.contains(value);
2729+
2730+
}
2731+
2732+
protected boolean matchHeader(String key, Header header) {
2733+
return matchValue(key, this.headers) || matchExtension(header.getExtensions());
2734+
}
2735+
26542736
private boolean matchExtension(Map<String, Object> extensions) {
26552737
if (extensions == null || extensions.isEmpty() || vendorExtensions.isEmpty()) {
26562738
return false;
@@ -2660,15 +2742,9 @@ private boolean matchExtension(Map<String, Object> extensions) {
26602742
.anyMatch(this::matchExtension);
26612743
}
26622744

2663-
protected boolean matchExtension(Map.Entry<String, Object> entry) {
2745+
private boolean matchExtension(Map.Entry<String, Object> entry) {
26642746
Set<String> set = vendorExtensions.get(entry.getKey());
2665-
if (set == null) {
2666-
return false;
2667-
}
2668-
if (set == ANYSET) {
2669-
return true;
2670-
}
2671-
return set.contains(entry.getValue());
2747+
return matchValue(entry.getValue(), set);
26722748
}
26732749

26742750
private Set<String> getAnySet(boolean isTrue) {

0 commit comments

Comments
 (0)