/
utils.py
82 lines (61 loc) · 2.53 KB
/
utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import pathlib
from datetime import datetime, timedelta
from hashlib import blake2b
import json
def unchunk(chunked_data):
data = b""
while True:
line = chunked_data.readline()
if line == b"0\r\n": break
chunk_length = int(line[:-2], 16) + 2
chunk = chunked_data.read(chunk_length)[:-2]
data += chunk
return data
class Cache:
def __init__(self):
self.local_cache = pathlib.Path('./.cache')
if not self.local_cache.is_dir():
self.local_cache.mkdir()
def has_valid_cache(self, url):
hash_algo = blake2b(digest_size=20)
hash_algo.update(bytes(url, encoding='utf8'))
url_hash = hash_algo.hexdigest()
cache_file = self.local_cache / url_hash
if cache_file.is_file():
with cache_file.open() as cache:
expiry_date = cache.readline().strip()
if datetime.utcnow() < datetime.fromisoformat(expiry_date):
return True
cache_file.unlink()
return False
def store(self, url, headers, body):
hash_algo = blake2b(digest_size=20)
cache_control_header = headers.get('cache-control', False)
if cache_control_header and 'max-age' in cache_control_header:
age = headers.get('age', 0)
_, max_age = cache_control_header.split('=', 1) # Input string 'max-age=<age>'
cache_time_left = int(max_age) - int(age)
caching_expiry = datetime.utcnow() + timedelta(seconds=cache_time_left)
hash_algo.update(bytes(url, encoding='utf8'))
url_hash = hash_algo.hexdigest()
self.local_cache.touch(url_hash)
cache_file = self.local_cache / url_hash
cache_content = bytes(
str(caching_expiry) + "\r\n" +
json.dumps(headers) + "\r\n" +
body + "\r\n",
encoding = 'utf8'
)
cache_file.write_bytes(cache_content)
def retrieve(self, url):
hash_algo = blake2b(digest_size=20)
hash_algo.update(bytes(url, encoding='utf8'))
url_hash = hash_algo.hexdigest()
cache_file = self.local_cache / url_hash
if cache_file.is_file():
with cache_file.open() as cache:
expiry_date = cache.readline() # Ignoring this line
headers = cache.readline().strip()
decoded_headers = json.loads(headers)
body = cache.read()
return decoded_headers, body