swiftsync/middlewares/last_modified.py
2013-04-02 17:42:56 +02:00

91 lines
3.4 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright (C) 2013 eNovance SAS <licensing@enovance.com>
#
# Author: Fabien Boucher <fabien.boucher@enovance.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import time
from swift.common.utils import get_logger
from swift.common.http import is_success
from swift.common.swob import wsgify
from swift.common.wsgi import make_pre_authed_request
class LastModifiedMiddleware(object):
"""
LastModified is a middleware that add a meta to a container
when that container and/or objects in it are modified. The meta
data will contains the epoch timestamp. This middleware aims
to be used with the synchronizer. It limits the tree parsing
by giving a way to know a container has been modified since the
last container synchronization.
Actions that lead to the container meta modification :
- POST/PUT on container
- POST/PUT/DELETE on object in it
The following shows an example of proxy-server.conf:
[pipeline:main]
pipeline = catch_errors cache tempauth last-modified proxy-server
[filter:last-modified]
use = egg:swift#last_modified
"""
def __init__(self, app, conf):
self.app = app
self.conf = conf
self.logger = get_logger(self.conf, log_route='last_modified')
def update_last_modified_meta(self, req, env):
vrs, account, container, obj = req.split_path(1, 4, True)
if obj:
path = env['PATH_INFO'].split('/%s' % obj)[0]
headers = {'X-Container-Meta-Last-Modified': str(time.time())}
set_meta_req = make_pre_authed_request(env,
method='POST',
path=path,
headers=headers,
environ=env,
swift_source='lm')
return set_meta_req.get_response(self.app)
def req_passthrough(self, req):
return req.get_response(self.app)
@wsgify
def __call__(self, req):
vrs, account, container, obj = req.split_path(1, 4, True)
if (req.method in ('POST', 'PUT') and
container or req.method == 'DELETE' and obj):
new_env = req.environ.copy()
user_resp = self.req_passthrough(req)
if is_success(user_resp.status_int):
# Update Container Meta Last-Modified in case of
# successful request
update_resp = self.update_last_modified_meta(req,
new_env)
if is_success(update_resp.status_int):
self.logger.info('Unable to update Meta Last-Modified')
return user_resp
return self.app
def filter_factory(global_conf, **local_conf):
conf = global_conf.copy()
conf.update(local_conf)
return lambda app: LastModifiedMiddleware(app, conf)