Skip to content

Commit 05a9860

Browse files
authored
[notification-hubs] fix TypeError when parsing AppleTemplateRegistrationDescription (#36114)
Currently `getHeadersOrUndefined` incorrectly assumes that the `ApnsHeaders` parsed from XML is always an array. However, for single XML element the XML parser gives back an object instead. This change ensures we are iterating over an array. One alternative approach is to add an option to `core-xml` specifying whether to treat certain single xml elements as an object or the single item of an array. Our underlying XML parser `fast-xml-parser` allows passing in a `isArray: (name, jpath, isLeafNode, isAttribute) => boolean` predicate but it is specific to `fast-xml-parser` and it needs more discussion on how to properly expose it in `core-xml`. For this targeted scenario, it is good enough to check whether the parsed result is an array. This package uses same pattern in other places too, for example, https://github.com/Azure/azure-sdk-for-js/blob/953fcf9f84b/sdk/notificationhubs/notification-hubs/src/serializers/notificationHubJobSerializer.ts#L61
1 parent cdbd31b commit 05a9860

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

sdk/notificationhubs/notification-hubs/CHANGELOG.md

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
# Release History
22

3-
## 2.0.2 (Unreleased)
4-
5-
### Features Added
6-
7-
### Breaking Changes
3+
## 2.0.2 (2025-10-07)
84

95
### Bugs Fixed
106

11-
### Other Changes
7+
- Properly handle single-element headers of template registrations [PR #36114](https://github.com/Azure/azure-sdk-for-js/pull/36114).
128

139
## 2.0.0 (2024-10-14)
1410

sdk/notificationhubs/notification-hubs/src/serializers/registrationSerializer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,14 +502,14 @@ export const registrationDescriptionParser: RegistrationDescriptionParser = {
502502
};
503503

504504
function getHeadersOrUndefined(
505-
value?: { Header: string; Value: string }[],
505+
value?: { Header: string; Value: string }[] | { Header: string; Value: string },
506506
): Record<string, string> | undefined {
507507
if (!isDefined(value)) {
508508
return undefined;
509509
}
510510

511511
const headerObj: Record<string, string> = {};
512-
for (const { Header, Value } of value) {
512+
for (const { Header, Value } of Array.isArray(value) ? value : [value]) {
513513
headerObj[Header] = Value;
514514
}
515515

sdk/notificationhubs/notification-hubs/test/internal/unit/registrationSerializer.spec.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,24 @@ const APPLE_TEMPLATE_REGISTRATION = `<?xml version="1.0" encoding="utf-8"?>
101101
</content>
102102
</entry>`;
103103

104+
const APPLE_TEMPLATE_REGISTRATION_SINGLE_APNSHEADER = `<?xml version="1.0" encoding="utf-8"?>
105+
<entry xmlns="http://www.w3.org/2005/Atom">
106+
<content type="application/xml">
107+
<AppleTemplateRegistrationDescription xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/netservices/2010/10/servicebus/connect">
108+
<Tags>myTag,myOtherTag</Tags>
109+
<RegistrationId>{Registration Id}</RegistrationId>
110+
<DeviceToken>{DeviceToken}</DeviceToken>
111+
<BodyTemplate><![CDATA[{Template for the body}]]></BodyTemplate>
112+
<ApnsHeaders>
113+
<ApnsHeader>
114+
<Header>apns-priority</Header>
115+
<Value>10</Value>
116+
</ApnsHeader>
117+
</ApnsHeaders>
118+
</AppleTemplateRegistrationDescription>
119+
</content>
120+
</entry>`;
121+
104122
const BAIDU_REGISTRATION = `<?xml version="1.0" encoding="utf-8"?>
105123
<entry xmlns="http://www.w3.org/2005/Atom">
106124
<content type="application/xml">
@@ -337,6 +355,19 @@ describe("parseRegistrationEntry", () => {
337355
assert.equal(registration.apnsHeaders!["apns-expiration"], "0");
338356
});
339357

358+
it("should parse an apple template registration description with single apns header", async () => {
359+
const registration = (await registrationDescriptionParser.parseRegistrationEntry(
360+
APPLE_TEMPLATE_REGISTRATION_SINGLE_APNSHEADER,
361+
)) as AppleTemplateRegistrationDescription;
362+
363+
assert.equal(registration.kind, "AppleTemplate");
364+
assert.equal(registration.registrationId, "{Registration Id}");
365+
assert.equal(registration.deviceToken, "{DeviceToken}");
366+
assert.deepEqual(registration.tags, ["myTag", "myOtherTag"]);
367+
assert.equal(registration.bodyTemplate, "{Template for the body}");
368+
assert.equal(registration.apnsHeaders!["apns-priority"], "10");
369+
});
370+
340371
it("should parse an Baidu registration description", async () => {
341372
const registration = (await registrationDescriptionParser.parseRegistrationEntry(
342373
BAIDU_REGISTRATION,

0 commit comments

Comments
 (0)