diff options
author | danielhanrahan <daniel.hanrahan@est.tech> | 2024-11-22 09:20:03 +0000 |
---|---|---|
committer | danielhanrahan <daniel.hanrahan@est.tech> | 2024-11-22 10:19:20 +0000 |
commit | d378e7b4321bf940424079440461eb0b874ad096 (patch) | |
tree | 7d208329ce03aeb339bdd89644b6cdb72e29a035 | |
parent | 225626a21199cbb8fbab976169785313b3aeceb7 (diff) |
Make Content-Type header default to JSON for CPS APIs
Recent changes for XML support have made Content-Type header
mandatory, where before it was not. This change makes CPS
default to JSON if Content-Type is not specified.
Issue-ID: CPS-2517
Signed-off-by: danielhanrahan <daniel.hanrahan@est.tech>
Change-Id: Ic3718bfe7aedd6fe9dbd978f520179b184c9c932
5 files changed, 73 insertions, 41 deletions
diff --git a/cps-rest/docs/openapi/components.yml b/cps-rest/docs/openapi/components.yml index 728295fd31..1db4185330 100644 --- a/cps-rest/docs/openapi/components.yml +++ b/cps-rest/docs/openapi/components.yml @@ -291,12 +291,13 @@ components: name: Content-Type in: header description: Content type in header + required: false schema: type: string enum: - application/json - application/xml - required: true + default: application/json descendantsInQuery: name: descendants in: query diff --git a/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java b/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java index 6d22581845..dda88e019c 100755 --- a/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java +++ b/cps-rest/src/main/java/org/onap/cps/rest/controller/DataRestController.java @@ -72,9 +72,9 @@ public class DataRestController implements CpsDataApi { @Override public ResponseEntity<String> createNode(final String apiVersion, final String dataspaceName, final String anchorName, - final String contentTypeInHeader, final String nodeData, final String parentNodeXpath, - final Boolean dryRunEnabled, final String observedTimestamp) { + final Boolean dryRunEnabled, final String observedTimestamp, + final String contentTypeInHeader) { final ContentType contentType = ContentType.fromString(contentTypeInHeader); if (Boolean.TRUE.equals(dryRunEnabled)) { cpsDataService.validateData(dataspaceName, anchorName, parentNodeXpath, nodeData, contentType); @@ -92,19 +92,18 @@ public class DataRestController implements CpsDataApi { } @Override - public ResponseEntity<Void> deleteDataNode(final String apiVersion, - final String dataspaceName, final String anchorName, - final String xpath, final String observedTimestamp) { - cpsDataService.deleteDataNode(dataspaceName, anchorName, xpath, - toOffsetDateTime(observedTimestamp)); + public ResponseEntity<Void> deleteDataNode(final String apiVersion, final String dataspaceName, + final String anchorName, final String xpath, + final String observedTimestamp) { + cpsDataService.deleteDataNode(dataspaceName, anchorName, xpath, toOffsetDateTime(observedTimestamp)); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } @Override public ResponseEntity<String> addListElements(final String apiVersion, final String dataspaceName, final String anchorName, final String parentNodeXpath, - final String contentTypeInHeader, final String nodeData, - final String observedTimestamp) { + final String nodeData, final String observedTimestamp, + final String contentTypeInHeader) { final ContentType contentType = ContentType.fromString(contentTypeInHeader); cpsDataService.saveListElements(dataspaceName, anchorName, parentNodeXpath, nodeData, toOffsetDateTime(observedTimestamp), contentType); @@ -115,7 +114,9 @@ public class DataRestController implements CpsDataApi { @Timed(value = "cps.data.controller.datanode.get.v1", description = "Time taken to get data node") public ResponseEntity<Object> getNodeByDataspaceAndAnchor(final String dataspaceName, - final String anchorName, final String xpath, final Boolean includeDescendants) { + final String anchorName, + final String xpath, + final Boolean includeDescendants) { final FetchDescendantsOption fetchDescendantsOption = Boolean.TRUE.equals(includeDescendants) ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS : FetchDescendantsOption.OMIT_DESCENDANTS; final DataNode dataNode = cpsDataService.getDataNodes(dataspaceName, anchorName, xpath, @@ -129,8 +130,9 @@ public class DataRestController implements CpsDataApi { @Timed(value = "cps.data.controller.datanode.get.v2", description = "Time taken to get data node") public ResponseEntity<Object> getNodeByDataspaceAndAnchorV2(final String dataspaceName, final String anchorName, - final String contentTypeInHeader, final String xpath, - final String fetchDescendantsOptionAsString) { + final String xpath, + final String fetchDescendantsOptionAsString, + final String contentTypeInHeader) { final ContentType contentType = ContentType.fromString(contentTypeInHeader); final FetchDescendantsOption fetchDescendantsOption = FetchDescendantsOption.getFetchDescendantsOption(fetchDescendantsOptionAsString); @@ -148,9 +150,9 @@ public class DataRestController implements CpsDataApi { @Override public ResponseEntity<Object> updateNodeLeaves(final String apiVersion, final String dataspaceName, - final String anchorName, final String contentTypeInHeader, - final String nodeData, final String parentNodeXpath, - final String observedTimestamp) { + final String anchorName, final String nodeData, + final String parentNodeXpath, final String observedTimestamp, + final String contentTypeInHeader) { final ContentType contentType = ContentType.fromString(contentTypeInHeader); cpsDataService.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath, nodeData, toOffsetDateTime(observedTimestamp), contentType); @@ -159,9 +161,9 @@ public class DataRestController implements CpsDataApi { @Override public ResponseEntity<Object> replaceNode(final String apiVersion, final String dataspaceName, - final String anchorName, final String contentTypeInHeader, - final String nodeData, final String parentNodeXpath, - final String observedTimestamp) { + final String anchorName, final String nodeData, + final String parentNodeXpath, final String observedTimestamp, + final String contentTypeInHeader) { final ContentType contentType = ContentType.fromString(contentTypeInHeader); cpsDataService.updateDataNodeAndDescendants(dataspaceName, anchorName, parentNodeXpath, nodeData, toOffsetDateTime(observedTimestamp), contentType); @@ -169,10 +171,9 @@ public class DataRestController implements CpsDataApi { } @Override - public ResponseEntity<Object> replaceListContent(final String apiVersion, - final String dataspaceName, final String anchorName, - final String parentNodeXpath, final Object jsonData, - final String observedTimestamp) { + public ResponseEntity<Object> replaceListContent(final String apiVersion, final String dataspaceName, + final String anchorName, final String parentNodeXpath, + final Object jsonData, final String observedTimestamp) { cpsDataService.replaceListContent(dataspaceName, anchorName, parentNodeXpath, jsonObjectMapper.asJsonString(jsonData), toOffsetDateTime(observedTimestamp)); return new ResponseEntity<>(HttpStatus.OK); @@ -180,7 +181,7 @@ public class DataRestController implements CpsDataApi { @Override public ResponseEntity<Void> deleteListOrListElement(final String dataspaceName, final String anchorName, - final String listElementXpath, final String observedTimestamp) { + final String listElementXpath, final String observedTimestamp) { cpsDataService .deleteListOrListElement(dataspaceName, anchorName, listElementXpath, toOffsetDateTime(observedTimestamp)); return new ResponseEntity<>(HttpStatus.NO_CONTENT); @@ -211,10 +212,10 @@ public class DataRestController implements CpsDataApi { @Timed(value = "cps.data.controller.get.delta", description = "Time taken to get delta between anchors") public ResponseEntity<Object> getDeltaByDataspaceAndAnchors(final String dataspaceName, - final String sourceAnchorName, - final String targetAnchorName, - final String xpath, - final String descendants) { + final String sourceAnchorName, + final String targetAnchorName, + final String xpath, + final String descendants) { final FetchDescendantsOption fetchDescendantsOption = FetchDescendantsOption.getFetchDescendantsOption(descendants); diff --git a/cps-rest/src/main/java/org/onap/cps/rest/controller/QueryRestController.java b/cps-rest/src/main/java/org/onap/cps/rest/controller/QueryRestController.java index 6823f6b03e..b425333f9e 100644 --- a/cps-rest/src/main/java/org/onap/cps/rest/controller/QueryRestController.java +++ b/cps-rest/src/main/java/org/onap/cps/rest/controller/QueryRestController.java @@ -60,7 +60,9 @@ public class QueryRestController implements CpsQueryApi { @Timed(value = "cps.data.controller.datanode.query.v1", description = "Time taken to query data nodes") public ResponseEntity<Object> getNodesByDataspaceAndAnchorAndCpsPath(final String dataspaceName, - final String anchorName, final String cpsPath, final Boolean includeDescendants) { + final String anchorName, + final String cpsPath, + final Boolean includeDescendants) { final FetchDescendantsOption fetchDescendantsOption = Boolean.TRUE.equals(includeDescendants) ? FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS : FetchDescendantsOption.OMIT_DESCENDANTS; return executeNodesByDataspaceQueryAndCreateResponse(dataspaceName, anchorName, cpsPath, @@ -71,8 +73,10 @@ public class QueryRestController implements CpsQueryApi { @Timed(value = "cps.data.controller.datanode.query.v2", description = "Time taken to query data nodes") public ResponseEntity<Object> getNodesByDataspaceAndAnchorAndCpsPathV2(final String dataspaceName, - final String anchorName, final String contentTypeInHeader, final String cpsPath, - final String fetchDescendantsOptionAsString) { + final String anchorName, + final String cpsPath, + final String fetchDescendantsOptionAsString, + final String contentTypeInHeader) { final ContentType contentType = ContentType.fromString(contentTypeInHeader); final FetchDescendantsOption fetchDescendantsOption = FetchDescendantsOption.getFetchDescendantsOption(fetchDescendantsOptionAsString); @@ -83,9 +87,11 @@ public class QueryRestController implements CpsQueryApi { @Override @Timed(value = "cps.data.controller.datanode.query.across.anchors", description = "Time taken to query data nodes across anchors") - public ResponseEntity<Object> getNodesByDataspaceAndCpsPath(final String dataspaceName, final String cpsPath, + public ResponseEntity<Object> getNodesByDataspaceAndCpsPath(final String dataspaceName, + final String cpsPath, final String fetchDescendantsOptionAsString, - final Integer pageIndex, final Integer pageSize) { + final Integer pageIndex, + final Integer pageSize) { final FetchDescendantsOption fetchDescendantsOption = FetchDescendantsOption.getFetchDescendantsOption(fetchDescendantsOptionAsString); final PaginationOption paginationOption = (pageIndex == null || pageSize == null) @@ -111,7 +117,7 @@ public class QueryRestController implements CpsQueryApi { } private Integer getTotalPages(final String dataspaceName, final String cpsPath, - final PaginationOption paginationOption) { + final PaginationOption paginationOption) { if (paginationOption == PaginationOption.NO_PAGINATION) { return 1; } diff --git a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy index 27738b07c6..72ae4c7f91 100755 --- a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy +++ b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/DataRestControllerSpec.groovy @@ -328,6 +328,23 @@ class DataRestControllerSpec extends Specification { assert numberOfDataTrees == 2 } + def 'Get all the data trees using V2 without Content-Type defaults to json'() { + given: 'the service returns all data node leaves' + def xpath = '/' + def endpoint = "$dataNodeBaseEndpointV2/anchors/$anchorName/node" + mockCpsDataService.getDataNodes(dataspaceName, anchorName, xpath, OMIT_DESCENDANTS) >> [dataNodeWithLeavesNoChildren, dataNodeWithLeavesNoChildren2] + when: 'V2 of get request is performed through REST API without specifying content-type header' + def response = + mvc.perform(get(endpoint) + .param('xpath', xpath)) + .andReturn().response + then: 'a success response is returned' + response.status == HttpStatus.OK.value() + and: 'the response contains the datanode in json array format' + response.getContentAsString() == '[{"parent-1":{"leaf":"value","leafList":["leaveListElement1","leaveListElement2"]}},' + + '{"parent-2":{"leaf":"value"}}]' + } + def 'Get all the data trees as XML with root node xPath using V2'() { given: 'the service returns all data node leaves' def xpath = '/' diff --git a/docs/api/swagger/cps/openapi.yaml b/docs/api/swagger/cps/openapi.yaml index 3b6bd43d6c..812a2e4e60 100644 --- a/docs/api/swagger/cps/openapi.yaml +++ b/docs/api/swagger/cps/openapi.yaml @@ -1165,8 +1165,9 @@ paths: - description: Content type in header in: header name: Content-Type - required: true + required: false schema: + default: application/json enum: - application/json - application/xml @@ -1363,8 +1364,9 @@ paths: - description: Content type in header in: header name: Content-Type - required: true + required: false schema: + default: application/json enum: - application/json - application/xml @@ -1490,8 +1492,9 @@ paths: - description: Content type in header in: header name: Content-Type - required: true + required: false schema: + default: application/json enum: - application/json - application/xml @@ -1617,8 +1620,9 @@ paths: - description: Content type in header in: header name: Content-Type - required: true + required: false schema: + default: application/json enum: - application/json - application/xml @@ -1810,8 +1814,9 @@ paths: - description: Content type in header in: header name: Content-Type - required: true + required: false schema: + default: application/json enum: - application/json - application/xml @@ -2286,8 +2291,9 @@ paths: - description: Content type in header in: header name: Content-Type - required: true + required: false schema: + default: application/json enum: - application/json - application/xml @@ -2591,8 +2597,9 @@ components: description: Content type in header in: header name: Content-Type - required: true + required: false schema: + default: application/json enum: - application/json - application/xml |