CBOR support for the DDI API (#797)

* Add test for default content-type of DDI

We want to add support for other content types to the DDI interface.
To make sure we don't break devices that implicitly assume they will
receive JSON without setting an Accept header, add a test for the current
behavior.

v2: Complete the assertion

Signed-off-by: Stefan Schake <stefan.schake@devolo.de>

* Add CBOR support for DDI API

Concise Binary Object Representation (CBOR) is a binary data format
optimized for small code and message size. Since Spring Boot 2, there
is an autoconfigured data converter so we need to do little more than
add the reference to the Jackson backend and advertise support in the DDI
endpoints. Add tests to ensure all endpoints support the format.

Fixes #748

Signed-off-by: Stefan Schake <stefan.schake@devolo.de>
This commit is contained in:
Stefan Schake
2019-02-28 18:32:48 +01:00
committed by Dominic Schabel
parent d29bcc0345
commit e8e203b69a
8 changed files with 185 additions and 8 deletions

View File

@@ -50,6 +50,19 @@ public final class DdiRestConstants {
*/
public static final String NO_ACTION_HISTORY = "0";
/**
* Media type for CBOR content. Unfortunately, there is no other constant we
* can reuse - even the Jackson data converter simply hardcodes this.
*/
public static final String MEDIA_TYPE_CBOR = "application/cbor";
/**
* Media type for CBOR content with strings encoded as UTF-8. Technically
* redundant since CBOR always uses UTF-8, but Spring will append it
* regardless.
*/
public static final String MEDIA_TYPE_CBOR_UTF8 = "application/cbor;charset=UTF-8";
private DdiRestConstants() {
// constant class, private constructor.
}

View File

@@ -50,7 +50,7 @@ public interface DdiRootControllerRestApi {
* @return the response
*/
@GetMapping(value = "/{controllerId}/softwaremodules/{softwareModuleId}/artifacts", produces = {
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE, DdiRestConstants.MEDIA_TYPE_CBOR })
ResponseEntity<List<DdiArtifact>> getSoftwareModulesArtifacts(@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") final String controllerId,
@PathVariable("softwareModuleId") final Long softwareModuleId);
@@ -66,7 +66,8 @@ public interface DdiRootControllerRestApi {
* the HTTP request injected by spring
* @return the response
*/
@GetMapping(value = "/{controllerId}", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
@GetMapping(value = "/{controllerId}", produces = { MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE,
DdiRestConstants.MEDIA_TYPE_CBOR })
ResponseEntity<DdiControllerBase> getControllerBase(@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") final String controllerId);
@@ -154,7 +155,7 @@ public interface DdiRootControllerRestApi {
* @return the response
*/
@GetMapping(value = "/{controllerId}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION + "/{actionId}", produces = {
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE, DdiRestConstants.MEDIA_TYPE_CBOR })
ResponseEntity<DdiDeploymentBase> getControllerBasedeploymentAction(@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") @NotEmpty final String controllerId,
@PathVariable("actionId") @NotEmpty final Long actionId,
@@ -178,7 +179,8 @@ public interface DdiRootControllerRestApi {
* @return the response
*/
@PostMapping(value = "/{controllerId}/" + DdiRestConstants.DEPLOYMENT_BASE_ACTION + "/{actionId}/"
+ DdiRestConstants.FEEDBACK, consumes = MediaType.APPLICATION_JSON_VALUE)
+ DdiRestConstants.FEEDBACK, consumes = { MediaType.APPLICATION_JSON_VALUE,
DdiRestConstants.MEDIA_TYPE_CBOR })
ResponseEntity<Void> postBasedeploymentActionFeedback(@Valid final DdiActionFeedback feedback,
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId,
@PathVariable("actionId") @NotEmpty final Long actionId);
@@ -197,8 +199,8 @@ public interface DdiRootControllerRestApi {
*
* @return status of the request
*/
@PutMapping(value = "/{controllerId}/"
+ DdiRestConstants.CONFIG_DATA_ACTION, consumes = MediaType.APPLICATION_JSON_VALUE)
@PutMapping(value = "/{controllerId}/" + DdiRestConstants.CONFIG_DATA_ACTION, consumes = {
MediaType.APPLICATION_JSON_VALUE, DdiRestConstants.MEDIA_TYPE_CBOR })
ResponseEntity<Void> putConfigData(@Valid final DdiConfigData configData,
@PathVariable("tenant") final String tenant, @PathVariable("controllerId") final String controllerId);
@@ -217,7 +219,7 @@ public interface DdiRootControllerRestApi {
* @return the {@link DdiCancel} response
*/
@GetMapping(value = "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION + "/{actionId}", produces = {
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE })
MediaTypes.HAL_JSON_VALUE, MediaType.APPLICATION_JSON_VALUE, DdiRestConstants.MEDIA_TYPE_CBOR })
ResponseEntity<DdiCancel> getControllerCancelAction(@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") @NotEmpty final String controllerId,
@PathVariable("actionId") @NotEmpty final Long actionId);
@@ -241,7 +243,8 @@ public interface DdiRootControllerRestApi {
*/
@PostMapping(value = "/{controllerId}/" + DdiRestConstants.CANCEL_ACTION + "/{actionId}/"
+ DdiRestConstants.FEEDBACK, consumes = MediaType.APPLICATION_JSON_VALUE)
+ DdiRestConstants.FEEDBACK, consumes = { MediaType.APPLICATION_JSON_VALUE,
DdiRestConstants.MEDIA_TYPE_CBOR })
ResponseEntity<Void> postCancelActionFeedback(@Valid final DdiActionFeedback feedback,
@PathVariable("tenant") final String tenant,
@PathVariable("controllerId") @NotEmpty final String controllerId,