forget-cancellare-vecchi-toot/lib/img_proxy.py

52 lines
1.8 KiB
Python

import requests
import threading
import redis
from flask import make_response, abort
class ImgProxyCache(object):
def __init__(self, redis_uri='redis://', timeout=1, expire=60*60*24,
prefix='img_proxy'):
self.redis = redis.StrictRedis.from_url(redis_uri)
self.timeout = timeout
self.expire = expire
self.prefix = prefix
self.redis.client_setname('img_proxy')
def key(self, keytype, url):
return '{prefix}:{keytype}:{url}'.format(
prefix=self.prefix,
keytype=keytype,
url=url)
def fetch_and_cache(self, url):
resp = requests.get(url)
if(resp.status_code != 200):
return
mime = resp.headers.get('content-type', 'application/octet-stream')
self.redis.set(self.key('mime', url),
mime, px=self.expire*1000)
self.redis.set(self.key('body', url),
resp.content, px=self.expire*1000)
def respond(self, url):
x_imgproxy_cache = 'HIT'
mime = self.redis.get(self.key('mime', url))
body = self.redis.get(self.key('body', url))
if not body or not mime:
x_imgproxy_cache = 'MISS'
if self.redis.set(
self.key('lock', url), 1, nx=True, ex=10*self.timeout):
t = threading.Thread(target=self.fetch_and_cache, args=(url,))
t.start()
t.join(self.timeout)
mime = self.redis.get(self.key('mime', url))
body = self.redis.get(self.key('body', url))
if not body or not mime:
return abort(404)
resp = make_response(body, 200)
resp.headers.set('content-type', mime)
resp.headers.set('x-imgproxy-cache', x_imgproxy_cache)
return resp