Skip to content

Commit 0f99003

Browse files
authored
fix #404 (#496)
<!--- Provide a general summary of your changes in the title above --> <!--- Link the corresponding issues after you created the pull request --> ## Types of changes <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [x] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) ## Checklist: <!--- Go over all the following points, and put an `x` in all the boxes that apply. --> <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [x] I have updated the [changelog](../CHANGELOG.md) accordingly. - [x] I have added tests to cover my changes.
1 parent 422e27d commit 0f99003

9 files changed

Lines changed: 236 additions & 218 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- the `http.client.NotConnected` raised by `SoapClient` now carries the reason of the underlying connection/SSL error, and the consumer now logs the SSL error when it falls back from an encrypted to an unencrypted connection [#427](https://github.com/Draegerwerk/sdc11073/issues/427)
1313

14+
### Fixed
15+
16+
- `SubscriptionEnd` messages now use the full WS-Eventing status URI (e.g. `http://schemas.xmlsoap.org/ws/2004/08/eventing/SourceShuttingDown`) instead of the bare local name, and are sent to the `EndTo` endpoint reference of the subscribe request. If no `EndTo` was provided, no `SubscriptionEnd` message is sent [#404](https://github.com/Draegerwerk/sdc11073/issues/404)
17+
- the parameter and return type in `RequestManipulatorProtocol.manipulate_string` from `str` to `bytes`
18+
1419
## [v3.0.0] - 2026-06-24
1520

1621
### Added

pat/requestmanipulator.py

Lines changed: 0 additions & 52 deletions
This file was deleted.

src/sdc11073/consumer/manipulator.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
"""A manipulator to manipulate outgoing messages."""
2+
13
from __future__ import annotations
24

35
from typing import TYPE_CHECKING, Protocol
46

57
if TYPE_CHECKING:
68
from sdc11073 import xml_utils
7-
89
from sdc11073.pysoap.soapenvelope import Soap12Envelope
910

1011

@@ -23,5 +24,5 @@ def manipulate_soapenvelope(self, soap_envelope: Soap12Envelope) -> Soap12Envelo
2324
def manipulate_domtree(self, domtree: xml_utils.LxmlElement) -> xml_utils.LxmlElement | None:
2425
"""Manipulate on etree.Element level."""
2526

26-
def manipulate_string(self, xml_string: str) -> str | None:
27+
def manipulate_string(self, xml_string: bytes) -> bytes | None:
2728
"""Manipulate on string level."""

src/sdc11073/provider/subscriptionmgr_async.py

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,12 @@
1414

1515
from sdc11073 import observableproperties
1616
from sdc11073.etc import apply_map
17+
from sdc11073.provider.subscriptionmgr_base import ActionBasedSubscription, RoundTripData, SubscriptionsManagerBase
1718
from sdc11073.pysoap.soapclient import HTTPReturnCodeError
1819
from sdc11073.xml_types import eventing_types as evt_types
1920
from sdc11073.xml_types.addressing_types import HeaderInformationBlock
2021
from sdc11073.xml_types.basetypes import MessageType
2122

22-
from .subscriptionmgr_base import ActionBasedSubscription, RoundTripData, SubscriptionsManagerBase
23-
2423
if TYPE_CHECKING:
2524
from collections.abc import Awaitable, Iterable
2625
from logging import LoggerAdapter
@@ -81,35 +80,27 @@ async def async_send_notification_report(self, body_node: xml_utils.LxmlElement,
8180
raise
8281

8382
async def async_send_notification_end_message(
84-
self, code: str = 'SourceShuttingDown', reason: str = 'Event source going off line.'
83+
self,
84+
code: str = evt_types.SubscriptionEndStatus.SOURCE_SHUTTING_DOWN,
85+
reason: str = 'Event source going off line.',
8586
) -> ReceivedMessage | None:
86-
"""Send notification end message to subscriber."""
87-
url = self.base_urls[0]
88-
my_addr = f'{url.scheme}:{url.netloc}/{url.path}'
87+
"""Send notification end message to subscriber.
8988
90-
if not self.is_valid:
89+
A SubscriptionEnd message is sent to the EndTo endpoint reference of the subscribe request.
90+
If no EndTo was provided, no message is sent.
91+
"""
92+
message = self._prepare_subscription_end(code=code, reason=reason)
93+
if message is None:
9194
return None
92-
subscription_end = evt_types.SubscriptionEnd()
93-
subscription_end.SubscriptionManager.Address = my_addr
94-
subscription_end.SubscriptionManager.ReferenceParameters = self.reference_parameters
95-
subscription_end.Status = code
96-
subscription_end.add_reason(reason, 'en-US')
97-
inf = HeaderInformationBlock(
98-
action=subscription_end.action,
99-
addr_to=self.end_to_address or self.notify_to_address,
100-
reference_parameters=self.end_to_ref_params or self.notify_ref_params,
101-
)
102-
message = self._msg_factory.mk_soap_message(inf, payload=subscription_end)
103-
url = self._end_to_url or self.notify_to_url
104-
soap_client = self._get_soap_client(url.netloc)
105-
self._logger.info('async send subscription end to {}, subscription = {}', url, self) # noqa: PLE1205
95+
soap_client = self._get_soap_client(self._end_to_url.netloc)
96+
self._logger.info('async send subscription end to {}, subscription = {}', self._end_to_url, self) # noqa: PLE1205
10697
try:
107-
return await soap_client.async_post_message_to(url.path, message)
98+
return await soap_client.async_post_message_to(self._end_to_url.path, message)
10899
except aiohttp.client_exceptions.ClientConnectorError:
109100
# it does not matter that we could not send the message - end is end ;)
110101
self._logger.info( # noqa: PLE1205
111102
'exception async send subscription end to {}, subscription = {}',
112-
url,
103+
self._end_to_url,
113104
self,
114105
)
115106
except Exception: # noqa: BLE001

src/sdc11073/provider/subscriptionmgr_base.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
import http.client
66
import time
7+
import urllib.parse
78
import uuid
89
from collections import deque
910
from threading import Thread
1011
from typing import TYPE_CHECKING, Any, Protocol
11-
from urllib.parse import urlparse
1212

1313
from lxml import etree
1414

@@ -22,7 +22,6 @@
2222
from sdc11073.xml_types.basetypes import MessageType
2323

2424
if TYPE_CHECKING:
25-
import urllib.parse
2625
from collections.abc import Sequence
2726
from urllib.parse import SplitResult
2827

@@ -104,16 +103,16 @@ def __init__( # noqa: PLR0913
104103

105104
self.mode = subscribe_request.Delivery.Mode
106105
self.notify_to_address = subscribe_request.Delivery.NotifyTo.Address
107-
self.notify_to_url = urlparse(self.notify_to_address)
106+
self.notify_to_url = urllib.parse.urlparse(self.notify_to_address)
108107
self.notify_ref_params = subscribe_request.Delivery.NotifyTo.ReferenceParameters
109108
self.end_to_address = None
110109
self.end_to_ref_params = []
111-
self._end_to_url = None
110+
self._end_to_url: urllib.parse.ParseResult | None = None
112111
if subscribe_request.EndTo is not None:
113112
self.end_to_address = subscribe_request.EndTo.Address
114113
self.end_to_ref_params = subscribe_request.EndTo.ReferenceParameters
115114
if self.end_to_address is not None:
116-
self._end_to_url = urlparse(self.end_to_address)
115+
self._end_to_url = urllib.parse.urlparse(self.end_to_address)
117116

118117
self.identifier_uuid = uuid.uuid4()
119118
self.reference_parameters = [] # default: no reference parameters
@@ -194,32 +193,47 @@ def is_valid(self) -> bool:
194193
return False
195194
return self.remaining_seconds > 0 and not self.has_delivery_failure
196195

197-
def send_notification_end_message(
196+
def _prepare_subscription_end(
198197
self,
199-
code: str = 'SourceShuttingDown',
198+
code: str = evt_types.SubscriptionEndStatus.SOURCE_SHUTTING_DOWN,
200199
reason: str = 'Event source going off line.',
201-
):
202-
"""Send a notification end message."""
200+
) -> CreatedMessage | None:
203201
url = self.base_urls[0]
204202
my_addr = f'{url.scheme}:{url.netloc}/{url.path}'
205203

206204
if not self.is_valid:
207-
return
205+
return None
206+
if self._end_to_url is None:
207+
# no EndTo endpoint reference -> per WS-Eventing the default is not to send this message
208+
return None
208209
subscription_end = evt_types.SubscriptionEnd()
209210
subscription_end.SubscriptionManager.Address = my_addr
210211
subscription_end.SubscriptionManager.ReferenceParameters = self.reference_parameters
211212
subscription_end.Status = code
212213
subscription_end.add_reason(reason, 'en-US')
213214
inf = HeaderInformationBlock(
214215
action=subscription_end.action,
215-
addr_to=self.end_to_address or self.notify_to_address,
216-
reference_parameters=self.end_to_ref_params or self.notify_ref_params,
216+
addr_to=self.end_to_address,
217+
reference_parameters=self.end_to_ref_params,
217218
)
218-
message = self._msg_factory.mk_soap_message(inf, payload=subscription_end)
219-
url = self._end_to_url or self.notify_to_url
220-
soap_client = self._get_soap_client(url.netloc)
219+
return self._msg_factory.mk_soap_message(inf, payload=subscription_end)
220+
221+
def send_notification_end_message(
222+
self,
223+
code: str = evt_types.SubscriptionEndStatus.SOURCE_SHUTTING_DOWN,
224+
reason: str = 'Event source going off line.',
225+
):
226+
"""Send a notification end message.
227+
228+
A SubscriptionEnd message is sent to the EndTo endpoint reference of the subscribe request.
229+
If no EndTo was provided, no message is sent.
230+
"""
231+
message = self._prepare_subscription_end(code=code, reason=reason)
232+
if message is None:
233+
return
234+
soap_client = self._get_soap_client(self._end_to_url.netloc)
221235
try:
222-
soap_client.post_message_to(url.path, message, msg='send_notification_end_message')
236+
soap_client.post_message_to(self._end_to_url.path, message, msg='send_notification_end_message')
223237
except Exception as ex: # noqa: BLE001
224238
# it does not matter that we could not send the message - end is end ;)
225239
self._logger.info('could not send subscription end message, error = {}', ex) # noqa: PLE1205

0 commit comments

Comments
 (0)