Skip to content

Commit 96964d7

Browse files
committed
Add option to set If-Match eTag for objects write requests
1 parent b9ab0a9 commit 96964d7

File tree

4 files changed

+81
-0
lines changed

4 files changed

+81
-0
lines changed

examples/native_sync/using_etag.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import os
2+
3+
from copy import deepcopy
4+
from pubnub.pubnub import PubNub
5+
from pubnub.pnconfiguration import PNConfiguration
6+
from pubnub.exceptions import PubNubException
7+
8+
config = PNConfiguration()
9+
config.publish_key = os.getenv('PUBLISH_KEY', default='demo')
10+
config.subscribe_key = os.getenv('SUBSCRIBE_KEY', default='demo')
11+
config.user_id = "example"
12+
13+
config_2 = deepcopy(config)
14+
config_2.user_id = "example_2"
15+
16+
pubnub = PubNub(config)
17+
pubnub_2 = PubNub(config_2)
18+
19+
sample_user = {
20+
"uuid": "SampleUser",
21+
"name": "John Doe",
22+
"email": "[email protected]",
23+
"custom": {"age": 42, "address": "123 Main St."},
24+
}
25+
26+
set_result = pubnub.set_uuid_metadata(
27+
**sample_user,
28+
include_custom=True,
29+
include_status=True,
30+
include_type=True
31+
).sync()
32+
33+
e_tag = set_result.result.data.get('eTag')
34+
35+
overwrite_result = pubnub_2.set_uuid_metadata(uuid="SampleUser", name="Jane Doe").sync()
36+
new_e_tag = overwrite_result.result.data.get('eTag')
37+
38+
# We get false because user is updated after it was read.
39+
print(f"{e_tag == new_e_tag=}")
40+
41+
# We modify the user and try to update it.
42+
updated_user = {**sample_user, "custom": {"age": 43, "address": "321 Other St."}}
43+
44+
45+
try:
46+
update_result = pubnub.set_uuid_metadata(
47+
**updated_user,
48+
include_custom=True,
49+
include_status=True,
50+
include_type=True
51+
).if_matches_etag(e_tag).sync()
52+
except PubNubException as e:
53+
# We get an exception and after reading the error message we can see that the reason is that the eTag is outdated.
54+
print(f"Update failed: {e.get_error_message().get('message')}")
55+

pubnub/endpoints/endpoint.py

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Endpoint(object):
2525

2626
__metaclass__ = ABCMeta
2727
_path = None
28+
_custom_headers: dict = None
2829

2930
def __init__(self, pubnub):
3031
self.pubnub = pubnub
@@ -100,6 +101,9 @@ def request_headers(self):
100101
if self.http_method() in [HttpMethod.POST, HttpMethod.PATCH]:
101102
headers["Content-type"] = "application/json"
102103

104+
if self._custom_headers:
105+
headers.update(self._custom_headers)
106+
103107
return headers
104108

105109
def build_file_upload_request(self):

pubnub/endpoints/objects_v2/objects_endpoint.py

+9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ class ObjectsEndpoint(Endpoint):
1717

1818
_includes: PNIncludes = None
1919

20+
__if_matches_etag: str = None
21+
22+
_custom_headers: dict = {}
23+
2024
def __init__(self, pubnub):
2125
Endpoint.__init__(self, pubnub)
2226

@@ -36,6 +40,11 @@ def validate_params(self):
3640
def validate_specific_params(self):
3741
pass
3842

43+
def if_matches_etag(self, etag: str):
44+
self.__if_matches_etag = etag
45+
self._custom_headers.update({"If-Match": etag})
46+
return self
47+
3948
def encoded_params(self):
4049
params = {}
4150
if isinstance(self, ListEndpoint):

pubnub/exceptions.py

+13
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
from json import loads, JSONDecodeError
2+
3+
14
class PubNubException(Exception):
25
def __init__(self, errormsg="", status_code=0, pn_error=None, status=None):
36
self._errormsg = errormsg
@@ -19,6 +22,16 @@ def _status(self):
1922
raise DeprecationWarning
2023
return self.status
2124

25+
def get_status_code(self):
26+
return self._status_code
27+
28+
def get_error_message(self):
29+
try:
30+
error = loads(self._errormsg)
31+
return error.get('error')
32+
except JSONDecodeError:
33+
return self._errormsg
34+
2235

2336
class PubNubAsyncioException(Exception):
2437
def __init__(self, result, status):

0 commit comments

Comments
 (0)