Skip to content

Commit 560b4ec

Browse files
authored
Merge pull request #128 from smartboxgroup/feature/response-format-option
New response_format and request_fallback parameters
2 parents d61777a + 814e4b7 commit 560b4ec

4 files changed

Lines changed: 45 additions & 2 deletions

File tree

Components/WebService/Rest/RestConfigurableProducer.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class RestConfigurableProducer extends AbstractWebServiceProducer implements Htt
3939
const VALIDATION_DISPLAY_MESSAGE = 'display_message';
4040
const VALIDATION_RECOVERABLE = 'recoverable';
4141
const REQUEST_EXPECTED_RESPONSE_TYPE = 'response_type';
42+
const REQUEST_EXPECTED_RESPONSE_FORMAT = 'response_format';
4243

4344
/**
4445
* @param $options
@@ -112,6 +113,7 @@ protected function request(ClientInterface $client, array $stepActionParams, arr
112113
self::VALIDATION,
113114
self::REQUEST_QUERY_PARAMETERS,
114115
self::REQUEST_BASE_URI,
116+
self::REQUEST_EXPECTED_RESPONSE_FORMAT
115117
]);
116118

117119
$stepParamsResolver->setAllowedValues(self::REQUEST_HTTP_VERB, ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']);
@@ -199,14 +201,19 @@ protected function request(ClientInterface $client, array $stepActionParams, arr
199201
$responseBody = $this->getSerializer()->deserialize(
200202
$responseContent,
201203
$params[self::REQUEST_EXPECTED_RESPONSE_TYPE],
202-
$encoding
204+
$params[self::REQUEST_EXPECTED_RESPONSE_FORMAT] ?? $encoding
203205
);
204206
} catch (RuntimeException $e) {
205207
// Assume that the exception is one of the JSON exceptions that will kill the workers
206208
if (RestConfigurableProtocol::ENCODING_JSON === $encoding && (JSON_ERROR_SYNTAX != json_last_error())) {
207209
throw new UnexpectedValueException($e->getMessage());
208210
}
209-
// if it cannot parse the response fallback to the textual content of the body
211+
212+
if (false === $endpointOptions[RestConfigurableProtocol::OPTION_RESPONSE_FALLBACK_ON_ERROR]) {
213+
throw $e;
214+
}
215+
216+
trigger_error('Falling back to the original response payload when the deserialization fails and a custom response format isn\'t defined will throw an exception in v3.', E_USER_DEPRECATED);
210217
$responseBody = $responseContent;
211218
}
212219
}

Components/WebService/Rest/RestConfigurableProtocol.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ class RestConfigurableProtocol extends ConfigurableWebserviceProtocol implements
1515
const OPTION_HEADERS = 'headers';
1616
const OPTION_AUTH = 'authentication';
1717
const OPTION_ENCODING = 'encoding';
18+
/** @deprecated: Will be removed on next major version. Fallback will not happen in v3. */
19+
const OPTION_RESPONSE_FALLBACK_ON_ERROR = 'response_fallback';
1820

1921
const ENCODING_JSON = 'json';
2022
const ENCODING_XML = 'xml';
@@ -58,6 +60,7 @@ public function configureOptionsResolver(OptionsResolver $resolver)
5860
self::OPTION_HEADERS => [],
5961
self::OPTION_AUTH => '',
6062
self::OPTION_ENCODING => self::ENCODING_JSON,
63+
self::OPTION_RESPONSE_FALLBACK_ON_ERROR => true,
6164
]);
6265

6366
$resolver->setRequired([
@@ -72,6 +75,7 @@ public function configureOptionsResolver(OptionsResolver $resolver)
7275
$resolver->setAllowedTypes(self::OPTION_AUTH, ['string', 'null']);
7376
$resolver->setAllowedTypes(self::OPTION_ENCODING, ['string']);
7477
$resolver->setAllowedValues(self::OPTION_ENCODING, [self::ENCODING_JSON, self::ENCODING_XML]);
78+
$resolver->setAllowedTypes(self::OPTION_RESPONSE_FALLBACK_ON_ERROR, ['boolean']);
7579
}
7680

7781
/**
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# 2. Deprecate the response fallback on the RestConfigurableProducer class
2+
3+
Date: 2020-05-08
4+
5+
## Status
6+
7+
Accepted
8+
9+
## Context
10+
11+
Currently the RestConfigurableProducer will pass the payload received from the target system to the serializer. If this one fails, it will catch the exception, fallback to the original response, **and continue the execution**.
12+
13+
This was done to allow certain APIs to return a non-deserializable response while still being able to continue the execution, either **by ignoring the payload** (i.e.: when the response code is enough) or to evaluate it to something else.
14+
15+
This makes the evaluator vulnerable, as it has no guarantee that what it will expect is something **that can be evaluated**.
16+
17+
Due to the fallback is present by default, one endpoint **could randomly fail** if the target system decides to send back a response in a format that is not expected by the application.
18+
19+
## Decision
20+
21+
We decided to deprecate the response fallback in this version and remove it **in the next major version**.
22+
23+
A new parameter was introduced in the `RestConfigurableProducer` (`response_format`) that will define the expected response format, and this format is passed to the deserialize function to instantiate the appropriate visitor. For example, a PlainTextVisitor could be implemented to process non-JSON responses while still producing **a evaluable object**. By default, if `response_format` is not setup, `encoding` will be passed.
24+
25+
## Consequences
26+
27+
In order to introduce this change in a backwards compatible way, a new boolean option was introduced in the `RestConfigurableProtocol` (`response_fallback`) that will prevent the fallback. Setting it to `false` **will throw an exception** when the payload cannot be deserialized.
28+
29+
## Metadata
30+
Authors: @andres.rey
31+
32+
People involved: @david.camprubi

0 commit comments

Comments
 (0)