Projet

Général

Profil

0001-remove-cache-on-metadata-view-6487.patch

Thomas Noël, 12 février 2015 14:47

Télécharger (4,76 ko)

Voir les différences:

Subject: [PATCH] remove cache on metadata view (#6487)

 authentic2/idp/saml/app_settings.py    |  1 -
 authentic2/idp/saml/saml2_endpoints.py |  4 +--
 authentic2/utils.py                    | 61 ----------------------------------
 3 files changed, 1 insertion(+), 65 deletions(-)
authentic2/idp/saml/app_settings.py
1 1
class AppSettings(object):
2 2
    __DEFAULTS = dict(
3 3
            ENABLE=False,
4
            LOCAL_METADATA_CACHE_TIMEOUT=600,
5 4
            METADATA_OPTIONS={},
6 5
            SECONDS_TOLERANCE=60,
7 6
            AUTHN_CONTEXT_FROM_SESSION=True,
authentic2/idp/saml/saml2_endpoints.py
75 75
from authentic2.idp import signals as idp_signals
76 76
# from authentic2.idp.models import *
77 77

  
78
from authentic2.utils import (cache_and_validate, get_backends as
79
        get_idp_backends, get_username, login_require)
78
from authentic2.utils import (get_backends as get_idp_backends, get_username, login_require)
80 79
from authentic2.decorators import is_transient_user
81 80
from authentic2.attributes_ng.engine import get_attributes
82 81

  
......
99 98
            lasso.SAML2_METADATA_BINDING_SOAP, '/artifact')
100 99
)
101 100

  
102
@cache_and_validate(lambda: app_settings.LOCAL_METADATA_CACHE_TIMEOUT)
103 101
def metadata(request):
104 102
    '''Endpoint to retrieve the metadata file'''
105 103
    logger.info('return metadata')
authentic2/utils.py
68 68
        return func
69 69

  
70 70

  
71
def cache_and_validate(timeout, hashing=hashlib.md5):
72
    '''
73
       Decorator to add caching, with support for ETag and Last-modified
74
       validation.
75

  
76
       Just give it the time for caching.
77
    '''
78
    def transform(f):
79
        f.cache = dict()
80
        def get_content(request, *args, **kwargs):
81
            '''
82
               Content is kept as
83

  
84
                (last_generation_time, last_modified_time, etag, content)
85

  
86
               inside the f.cache dictionnary
87
            '''
88
            key=args+tuple(sorted(kwargs.items()))
89
            if request.method == 'PURGE' and request.environ.get('REMOTE_ADDR') \
90
                    in settings.INTERNAL_IPS:
91
                # purge the cache place
92
                f.cache.pop(key, None)
93
            now = dt.datetime.now()
94
            if key in f.cache:
95
                date, last_modified, etag, mime_type, old_content = f.cache[key]
96
                if callable(timeout):
97
                    real_timeout = timeout()
98
                else:
99
                    real_timeout = timeout
100
                if now - date < dt.timedelta(seconds=real_timeout):
101
                    return date, last_modified, etag, mime_type, old_content
102
                else:
103
                    content = f(request, *args, **kwargs)
104
                    if old_content == content.content:
105
                        data = (now, last_modified, etag, mime_type, old_content)
106
                        return data
107
            else:
108
                content = f(request, *args, **kwargs)
109
            if content.status_code == 200:
110
                content_type = content.get('Content-Type', None)
111
                data = now, now, hashing(content.content).hexdigest(), content_type, content.content
112
                f.cache[key] = data
113
            else:
114
                data = None, None, None, None, content
115
            return data
116
        def get_last_modified(request, *args, **kwargs):
117
            _, last_modified, _, _, _ = get_content(request, *args, **kwargs)
118
            return last_modified
119
        def get_etag(request, *args, **kwargs):
120
            _, _, etag, _, _ = get_content(request, *args, **kwargs)
121
            return etag
122
        @condition(etag_func=get_etag, last_modified_func=get_last_modified)
123
        def replacement(request, *args, **kwargs):
124
            _, _, _, content_type, content = get_content(request, *args, **kwargs)
125
            if isinstance(content, six.string_types):
126
                return HttpResponse(content, content_type=content_type)
127
            else:
128
                return content
129
        return replacement
130
    return transform
131

  
132 71
def import_from(module, name):
133 72
    module = __import__(module, fromlist=[name])
134 73
    return getattr(module, name)
135
-