Skip to content

Instantly share code, notes, and snippets.

@mcm
Created November 16, 2017 23:50
Show Gist options
  • Save mcm/7ebc54bef05a37039d1f54f5667ab2e9 to your computer and use it in GitHub Desktop.
Save mcm/7ebc54bef05a37039d1f54f5667ab2e9 to your computer and use it in GitHub Desktop.
import http.cookiejar
import io
import boto3
import botocore
class S3CookieJar(http.cookiejar.LWPCookieJar):
bucket = None
filename = None
encryption_key = None
def save(self, filename=None, ignore_discard=False, ignore_expires=False):
if filename is None:
if self.filename is not None: filename = self.filename
else: raise ValueError(http.cookiejar.MISSING_FILENAME_TEXT)
session = boto3.Session()
f = io.BytesIO()
f.write(b"#LWP-Cookies-2.0\n")
f.write(self.as_lwp_str(ignore_discard, ignore_expires).encode())
f.seek(0)
if self.encryption_key:
kms = boto3.client("kms")
r = kms.encrypt(KeyId=self.encryption_key, Plaintext=f.getvalue())
f = io.BytesIO(r["CiphertextBlob"])
s3 = session.resource("s3")
bucket = s3.Bucket(self.bucket)
bucket.upload_fileobj(f, filename)
def load(self, filename=None, ignore_discard=False, ignore_expires=False):
if filename is None:
if self.filename is not None: filename = self.filename
else: raise ValueError(http.cookiejar.MISSING_FILENAME_TEXT)
f = io.BytesIO()
session = boto3.Session()
s3 = session.resource("s3")
bucket = s3.Bucket(self.bucket)
try:
bucket.download_fileobj(filename, f)
except botocore.exceptions.ClientError as e:
if e.response["Error"]["Code"] == "404":
# Don't error if the cookiejar doesn't exist yet
return
raise
if self.encryption_key:
kms = boto3.client("kms")
r = kms.decrypt(CiphertextBlob=f.getvalue())
f = io.BytesIO(r["Plaintext"])
f = io.StringIO(f.getvalue().decode())
try:
self._really_load(f, filename, ignore_discard, ignore_expires)
finally:
f.close()
"""
Usage:
import requests
cookiejar = S3CookieJar()
cookiejar.bucket = "my-bucket-name"
# Optional: specify the filename inside of the bucket (includes path)
#cookiejar.filename = "some/path/to/my/cookiejar"
# Optional: specify the ARN for a KMS key to use for encryption
#cookiejar.encryption_key = ""
session = requests.Session()
session.cookies = cookiejar
cookiejar.load("test.cookiejar", ignore_discard=True, ignore_expires=True)
print(cookiejar) # First time you run this, it'll be empty. The second time, it'll load from S3
session.get("http://httpbin.org/cookies/set?foo=bar")
print(cookiejar) # Confirm that there's a 'foo' cookie
cookiejar.save("test.cookiejar", ignore_discard=True, ignore_expires=True)
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment