Skip to content

Commit b448f0d

Browse files
committed
added Http method parse_cookies
1 parent b57c3dc commit b448f0d

File tree

2 files changed

+97
-5
lines changed

2 files changed

+97
-5
lines changed

osbot_utils/utils/Http.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import socket
55
import ssl
66
import unicodedata
7-
from time import sleep
8-
from urllib.parse import quote, urljoin, urlparse, urlunparse
9-
from urllib.request import Request, urlopen
7+
from http.cookies import SimpleCookie
8+
from time import sleep
9+
from urllib.parse import quote, urljoin, urlparse, urlunparse
10+
from urllib.request import Request, urlopen
1011

1112
from osbot_utils.utils.Str import html_decode
1213

@@ -78,6 +79,23 @@ def http_request(url, data=None, headers=None, method='GET', encoding ='utf-8',
7879
return result.decode(encoding)
7980
return result
8081

82+
83+
def parse_cookies(cookie_header):
84+
cookie = SimpleCookie()
85+
cookie.load(cookie_header)
86+
parsed_cookies = {}
87+
for key, morsel in cookie.items():
88+
cookie_attrs = {"value": morsel.value}
89+
for attr, value in morsel.items():
90+
if attr.lower() in ["secure", "httponly"]:
91+
cookie_attrs[attr] = (value == True)
92+
else:
93+
cookie_attrs[attr] = value.strip(', ') # we need to strip for the cases when there are multiple cookies split by , (as seen in FastAPI Test Client)
94+
parsed_cookies[key] = cookie_attrs
95+
96+
return parsed_cookies
97+
98+
8199
def port_is_not_open(port, host='0.0.0.0', timeout=1.0):
82100
return port_is_open(port, host,timeout) is False
83101

tests/unit/utils/test_Http.py

Lines changed: 76 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
from osbot_utils.utils.Objects import class_full_name, obj_data
88
from osbot_utils.testing.Temp_Web_Server import Temp_Web_Server
99
from osbot_utils.utils.Files import temp_file, file_not_exists, file_exists, file_bytes, file_size, file_create_bytes, file_delete, file_contents
10-
from osbot_utils.utils.Http import DELETE, POST, GET, GET_json, DELETE_json, GET_bytes, GET_bytes_to_file, \
10+
from osbot_utils.utils.Http import DELETE, POST, GET, GET_json, DELETE_json, GET_bytes, GET_bytes_to_file, \
1111
dns_ip_address, port_is_open, port_is_not_open, current_host_online, POST_json, OPTIONS, PUT_json, \
1212
is_port_open, wait_for_port, current_host_offline, http_request, wait_for_http, wait_for_ssh, \
13-
wait_for_port_closed, GET_to_file, url_join_safe
13+
wait_for_port_closed, GET_to_file, url_join_safe, parse_cookies
1414

1515

1616
# note: with the use of Custom_Handler_For_Http_Tests this test went from 10 seconds + to 17 ms :)
@@ -122,6 +122,80 @@ def test_is_port_open__port_is_open__port_is_not_open(self):
122122
assert port_is_not_open(host=host , port=port+1, timeout=timeout ) is True
123123
assert port_is_not_open(host=host_ip, port=port+1, timeout=timeout ) is True
124124

125+
def test_parse_cookies(self):
126+
# Main test with multiple cookies
127+
cookie_header = (
128+
'SESSION_ID__USER="user123"; expires=Tue, 29 Oct 2024 22:00:56 GMT; Max-Age=0; '
129+
'Path=/; SameSite=lax, SESSION_ID__PERSONA="persona456"; '
130+
'expires=Tue, 29 Oct 2024 22:00:56 GMT; Max-Age=0; Path=/; SameSite=lax'
131+
)
132+
parsed_cookies = parse_cookies(cookie_header)
133+
134+
assert len(parsed_cookies) == 2
135+
assert "SESSION_ID__USER" in parsed_cookies
136+
assert "SESSION_ID__PERSONA" in parsed_cookies
137+
138+
assert parsed_cookies["SESSION_ID__USER" ]["value" ] == "user123"
139+
assert parsed_cookies["SESSION_ID__PERSONA"]["value" ] == "persona456"
140+
141+
expected_expiry = "Tue, 29 Oct 2024 22:00:56 GMT"
142+
assert parsed_cookies["SESSION_ID__USER" ]["expires" ] == expected_expiry
143+
assert parsed_cookies["SESSION_ID__PERSONA"]["expires" ] == expected_expiry
144+
145+
assert parsed_cookies["SESSION_ID__USER" ]["path" ] == "/"
146+
assert parsed_cookies["SESSION_ID__PERSONA"]["path" ] == "/"
147+
148+
assert parsed_cookies["SESSION_ID__USER" ]["samesite"] == "lax"
149+
assert parsed_cookies["SESSION_ID__PERSONA"]["samesite"] == "lax"
150+
151+
assert parsed_cookies["SESSION_ID__USER" ]["max-age" ] == "0"
152+
assert parsed_cookies["SESSION_ID__PERSONA"]["max-age" ] == "0"
153+
154+
# Test cookies with secure and httponly flags
155+
cookie_header = (
156+
'SESSION_ID__USER="user123"; Secure; HttpOnly; Path=/; SameSite=strict, '
157+
'SESSION_ID__PERSONA="persona456"; Secure; Path=/; SameSite=none'
158+
)
159+
parsed_cookies = parse_cookies(cookie_header)
160+
161+
assert parsed_cookies["SESSION_ID__USER"]["value"] == "user123"
162+
assert parsed_cookies["SESSION_ID__USER"]["secure"] is True
163+
assert parsed_cookies["SESSION_ID__USER"]["httponly"] is True
164+
assert parsed_cookies["SESSION_ID__USER"]["path"] == "/"
165+
assert parsed_cookies["SESSION_ID__USER"]["samesite"] == "strict"
166+
167+
assert parsed_cookies["SESSION_ID__PERSONA"]["value"] == "persona456"
168+
assert parsed_cookies["SESSION_ID__PERSONA"]["secure"] is True
169+
assert parsed_cookies["SESSION_ID__PERSONA"]["httponly"] is False
170+
assert parsed_cookies["SESSION_ID__PERSONA"]["path"] == "/"
171+
assert parsed_cookies["SESSION_ID__PERSONA"]["samesite"] == "none"
172+
173+
174+
# Test empty cookie header
175+
cookie_header = ""
176+
parsed_cookies = parse_cookies(cookie_header)
177+
assert parsed_cookies == {}
178+
179+
180+
# Test with minimal attributes (no expires, max-age, path, samesite, secure, httponly)
181+
cookie_header = 'TEST_COOKIE="test_value"'
182+
parsed_cookies = parse_cookies(cookie_header)
183+
184+
assert len(parsed_cookies) == 1
185+
assert parsed_cookies["TEST_COOKIE"]["value"] == "test_value"
186+
assert parsed_cookies["TEST_COOKIE"] == {'comment' : '' ,
187+
'domain' : '' ,
188+
'expires' : '' ,
189+
'httponly': False ,
190+
'max-age' : '' ,
191+
'path' : '' ,
192+
'samesite': '' ,
193+
'secure' : False ,
194+
'value' : 'test_value',
195+
'version' : '' }
196+
197+
198+
125199
def test_wait_for_http(self):
126200
url = self.local_url
127201
assert wait_for_http(url) is True

0 commit comments

Comments
 (0)