Skip to content

Commit 2e355eb

Browse files
[Service Bus] Bug Fix: Correlation Rule Filter with the "label" doesn't filter the messages (Azure#13069)
### BUG Azure#13063 The correlation filter with the "subject" set using the `createRule` method doesn't filter the messages to the subscription. However, when we create the rule with the same correlation filter from the service bus explorer, messages get filtered as expected. ### CAUSE The key-value pairs having undefined/null as the values can be present in the request object at any level. They get serialized as empty tags in the XML request for the ATOM management operations. If such empty tags are present at the top level, the service throws a "Bad Request" error. This was handled by the SDK to make sure that the top-level of the request body doesn't have any empty tags. If such empty tags are present at the inner levels, the service assigns the empty strings as values to the empty tags instead of throwing an error. This wasn't handled and the empty tags at the rule filter created an unexpected filter for the subscription. This PR attempts to fix this issue. ### FIX The key-value pairs having undefined/null as the values are removed recursively from the object that is being serialized.
1 parent a72e5e2 commit 2e355eb

File tree

7 files changed

+420
-197
lines changed

7 files changed

+420
-197
lines changed

sdk/servicebus/service-bus/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
- Updates documentation for `ServiceBusMessage` to call out that the `body` field
1111
must be converted to a byte array or `Buffer` when cross-language
1212
compatibility while receiving events is required.
13+
- [Bug Fix] Correlation Rule Filter with the "label" set using the `createRule()` method doesn't filter the messages to the subscription.
14+
The bug has been fixed in [PR 13069](https://github.com/Azure/azure-sdk-for-js/pull/13069), also fixes the related issues where the messages are not filtered when a subset of properties are set in the correlation filter.
1315

1416
## 7.0.0 (2020-11-23)
1517

sdk/servicebus/service-bus/src/util/atomXmlHelper.ts

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { administrationLogger as logger } from "../log";
1919
import { Buffer } from "buffer";
2020

2121
import { parseURL } from "./parseUrl";
22+
import { isJSONLikeObject } from "./utils";
2223

2324
/**
2425
* @internal
@@ -91,6 +92,28 @@ export async function executeAtomXmlOperation(
9192
return serializer.deserialize(response);
9293
}
9394

95+
/**
96+
* @internal
97+
* @hidden
98+
* The key-value pairs having undefined/null as the values would lead to the empty tags in the serialized XML request.
99+
* Empty tags in the request body is problematic because of the following reasons.
100+
* - ATOM based management operations throw a "Bad Request" error if empty tags are included in the XML request body at top level.
101+
* - At the inner levels, Service assigns the empty strings as values to the empty tags instead of throwing an error.
102+
*
103+
* This method recursively removes the key-value pairs with undefined/null as the values from the request object that is to be serialized.
104+
*
105+
* @param {{ [key: string]: any }} resource
106+
*/
107+
export function sanitizeSerializableObject(resource: { [key: string]: any }) {
108+
Object.keys(resource).forEach(function(property) {
109+
if (resource[property] == undefined) {
110+
delete resource[property];
111+
} else if (isJSONLikeObject(resource[property])) {
112+
sanitizeSerializableObject(resource[property]);
113+
}
114+
});
115+
}
116+
94117
/**
95118
* @internal
96119
* @hidden
@@ -103,15 +126,8 @@ export async function executeAtomXmlOperation(
103126
export function serializeToAtomXmlRequest(resourceName: string, resource: any): object {
104127
const content: any = {};
105128

106-
// The top level key value pairs having undefined/null as the value are removed in order to address issue where the Service Bus'
107-
// ATOM based management operations throw a "Bad Request" error if empty tags are included in the xml request body at top level.
108-
const processedResource = Object.assign({}, resource);
109-
Object.keys(processedResource).forEach(function(property) {
110-
if (processedResource[property] == undefined) {
111-
delete processedResource[property];
112-
}
113-
});
114-
content[resourceName] = processedResource;
129+
content[resourceName] = Object.assign({}, resource);
130+
sanitizeSerializableObject(content[resourceName]);
115131

116132
content[resourceName][Constants.XML_METADATA_MARKER] = {
117133
xmlns: "http://schemas.microsoft.com/netservices/2010/10/servicebus/connect",

sdk/servicebus/service-bus/src/util/utils.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,33 @@ export function getBooleanOrUndefined(value: any): boolean | undefined {
282282
);
283283
}
284284

285+
/**
286+
* @internal
287+
* @hidden
288+
* Helps in differentiating JSON like objects from other kinds of objects.
289+
*/
290+
const EMPTY_JSON_OBJECT_CONSTRUCTOR = {}.constructor;
291+
285292
/**
286293
* @internal
287294
* @hidden
288295
* Returns `true` if given input is a JSON like object.
289296
* @param value
290297
*/
291298
export function isJSONLikeObject(value: any): boolean {
292-
return typeof value === "object" && !(value instanceof Number) && !(value instanceof String);
299+
// `value.constructor === {}.constructor` differentiates among the "object"s,
300+
// would filter the JSON objects and won't match any array or other kinds of objects
301+
302+
// -------------------------------------------------------------------------------
303+
// Few examples | typeof obj ==="object" | obj.constructor==={}.constructor
304+
// -------------------------------------------------------------------------------
305+
// {abc:1} | true | true
306+
// ["a","b"] | true | false
307+
// [{"a":1},{"b":2}] | true | false
308+
// new Date() | true | false
309+
// 123 | false | false
310+
// -------------------------------------------------------------------------------
311+
return typeof value === "object" && value.constructor === EMPTY_JSON_OBJECT_CONSTRUCTOR;
293312
}
294313

295314
/**

0 commit comments

Comments
 (0)