def send_entity(environ, start_response, entity): """ Send a :py:class:`bag <tiddlyweb.model.bag.Bag>` or :py:class:`recipe <tiddlyweb.model.recipe.Recipe>` out over HTTP, first :py:class:`serializing <tiddlyweb.serializer.Serializer>` to the correct type. If an incoming ``Etag`` validates, raise a ``304`` response. """ etag_string = entity_etag(environ, entity) check_incoming_etag(environ, etag_string) try: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) serializer.object = entity content = serializer.to_string() except NoSerializationError: raise HTTP415('Content type %s not supported' % mime_type) start_response("200 OK", [('Content-Type', mime_type), ('Cache-Control', 'no-cache'), ('ETag', etag_string), ('Vary', 'Accept')]) if isinstance(content, basestring): return [content] else: return content
def send_entity(environ, start_response, entity): """ Send a bag or recipe out HTTP, first serializing to the correct type. If the incoming etag matches, raise 304. """ etag_string = entity_etag(environ, entity) check_incoming_etag(environ, etag_string) try: serialize_type, mime_type = get_serialize_type(environ) serializer = Serializer(serialize_type, environ) serializer.object = entity content = serializer.to_string() except NoSerializationError: raise HTTP415('Content type %s not supported' % mime_type) start_response("200 OK", [('Content-Type', mime_type), ('Cache-Control', 'no-cache'), ('ETag', etag_string), ('Vary', 'Accept')]) if isinstance(content, basestring): return [content] else: return content
def validate_tiddler_headers(environ, tiddler): """ Check ETAG and last modified information to see if a) the client can use its cached tiddler b) we have edit contention when trying to write. """ request_method = environ['REQUEST_METHOD'] tiddlers_etag = tiddler_etag(environ, tiddler) LOGGER.debug('attempting to validate %s with revision %s', tiddler.title.encode('utf-8'), tiddler.revision) etag = None last_modified = None if request_method == 'GET': incoming_etag = check_incoming_etag(environ, tiddlers_etag) if not incoming_etag: # only check last-modified if no etag last_modified_string = http_date_from_timestamp( tiddler.modified) last_modified = ('Last-Modified', last_modified_string) check_last_modified(environ, last_modified_string) else: incoming_etag = environ.get('HTTP_IF_MATCH', None) LOGGER.debug('attempting to validate incoming etag(PUT):' '%s against %s', incoming_etag, tiddlers_etag) if incoming_etag and not _etag_write_match(incoming_etag, tiddlers_etag): raise HTTP412('Provided ETag does not match. ' 'Server content probably newer.') etag = ('Etag', '%s' % tiddlers_etag) return last_modified, etag
def _validate_tiddler_list(environ, tiddlers): """ Do Etag and Last modified checks on the collection of tiddlers. If ETag testing is done, no last modified handling is done, even if the ETag testing fails. If no 304 is raised, then just return last-modified and ETag for the caller to use in constructing its HTTP response. """ last_modified_string = http_date_from_timestamp(tiddlers.modified) last_modified = ('Last-Modified', last_modified_string) username = environ.get('tiddlyweb.usersign', {}).get('name', '') try: _, mime_type = get_serialize_type(environ) mime_type = mime_type.split(';', 1)[0].strip() except TypeError: mime_type = '' etag_string = '"%s:%s"' % (tiddlers.hexdigest(), sha('%s:%s' % (username, mime_type)).hexdigest()) etag = ('Etag', etag_string) incoming_etag = check_incoming_etag(environ, etag_string, last_modified=last_modified_string) if not incoming_etag: # only check last modified when no etag check_last_modified(environ, last_modified_string, etag=etag_string) return last_modified, etag
def _validate_tiddler_list(environ, tiddlers): """ Do Etag and Last modified checks on the collection of tiddlers. If ETag testing is done, no last modified handling is done, even if the ETag testing fails. If no 304 is raised, then just return last-modified and ETag for the caller to use in constructing its HTTP response. """ last_modified_string = http_date_from_timestamp(tiddlers.modified) last_modified = ('Last-Modified', last_modified_string) username = environ.get('tiddlyweb.usersign', {}).get('name', '') try: _, mime_type = get_serialize_type(environ) mime_type = mime_type.split(';', 1)[0].strip() except TypeError: mime_type = '' etag_string = '"%s:%s"' % (tiddlers.hexdigest(), sha('%s:%s' % (username.encode('utf-8'), mime_type)).hexdigest()) etag = ('Etag', etag_string) incoming_etag = check_incoming_etag(environ, etag_string) if not incoming_etag: # only check last modified when no etag check_last_modified(environ, last_modified_string) return last_modified, etag
def list_entities(environ, start_response, method_name, store_list=None, serializer_list=None): """ Get an optionally :py:mod:`filtered <tiddlyweb.filters>` list of all the :py:class:`bags <tiddlyweb.model.bag.Bag>` or :py:class:`recipes <tiddlyweb.model.recipe.Recipe>` the current ``tiddlyweb.usersign`` can read. """ store = environ['tiddlyweb.store'] serialize_type, mime_type = get_serialize_type(environ, collection=True) serializer = Serializer(serialize_type, environ) filters = environ['tiddlyweb.filters'] if method_name: if not store_list: store_list = getattr(store, method_name) if not serializer_list: serializer_list = getattr(serializer, method_name) try: kept_entities = _filter_readable(environ, store_list(), filters) except FilterError as exc: raise HTTP400(exc) etag_string = '"%s:%s"' % (kept_entities.hexdigest(), sha(mime_type).hexdigest()) check_incoming_etag(environ, etag_string) try: output = serializer_list(kept_entities) except NoSerializationError: raise HTTP415('Content type not supported: %s' % mime_type) start_response("200 OK", [('Content-Type', mime_type), ('Vary', 'Accept'), ('Cache-Control', 'no-cache'), ('Etag', etag_string)]) if isinstance(output, basestring): return [output] else: return output
def validate_tiddler_headers(environ, tiddler): """ Check ETag and last modified header information to see if a) on ``GET`` the user agent can use its cached tiddler b) on ``PUT`` we have edit contention. """ request_method = environ['REQUEST_METHOD'] this_tiddlers_etag = tiddler_etag(environ, tiddler) LOGGER.debug('attempting to validate %s with revision %s', tiddler.title, tiddler.revision) etag = None last_modified = None if request_method == 'GET': last_modified_string = http_date_from_timestamp(tiddler.modified) last_modified = ('Last-Modified', last_modified_string) cache_header = 'no-cache' if CACHE_CONTROL_FIELD in tiddler.fields: try: cache_header = 'max-age=%s' % int( tiddler.fields[CACHE_CONTROL_FIELD]) except ValueError: pass # if the value is not an int use default header incoming_etag = check_incoming_etag(environ, this_tiddlers_etag, last_modified=last_modified_string, cache_control=cache_header) if not incoming_etag: # only check last-modified if no etag check_last_modified(environ, last_modified_string, etag=this_tiddlers_etag, cache_control=cache_header) else: incoming_etag = environ.get('HTTP_IF_MATCH', None) LOGGER.debug( 'attempting to validate incoming etag(PUT):' '%s against %s', incoming_etag, this_tiddlers_etag) if incoming_etag and not _etag_write_match(incoming_etag, this_tiddlers_etag): raise HTTP412('Provided ETag does not match. ' 'Server content probably newer.') etag = ('ETag', '%s' % this_tiddlers_etag) return last_modified, etag
def validate_tiddler_headers(environ, tiddler): """ Check ETag and last modified header information to see if a) on ``GET`` the user agent can use its cached tiddler b) on ``PUT`` we have edit contention. """ request_method = environ['REQUEST_METHOD'] this_tiddlers_etag = tiddler_etag(environ, tiddler) LOGGER.debug('attempting to validate %s with revision %s', tiddler.title, tiddler.revision) etag = None last_modified = None if request_method == 'GET': last_modified_string = http_date_from_timestamp(tiddler.modified) last_modified = ('Last-Modified', last_modified_string) cache_header = 'no-cache' if CACHE_CONTROL_FIELD in tiddler.fields: try: cache_header = 'max-age=%s' % int( tiddler.fields[CACHE_CONTROL_FIELD]) except ValueError: pass # if the value is not an int use default header incoming_etag = check_incoming_etag(environ, this_tiddlers_etag, last_modified=last_modified_string, cache_control=cache_header) if not incoming_etag: # only check last-modified if no etag check_last_modified(environ, last_modified_string, etag=this_tiddlers_etag, cache_control=cache_header) else: incoming_etag = environ.get('HTTP_IF_MATCH', None) LOGGER.debug('attempting to validate incoming etag(PUT):' '%s against %s', incoming_etag, this_tiddlers_etag) if incoming_etag and not _etag_write_match(incoming_etag, this_tiddlers_etag): raise HTTP412('Provided ETag does not match. ' 'Server content probably newer.') etag = ('ETag', '%s' % this_tiddlers_etag) return last_modified, etag
serializer = Serializer(serialize_type, environ) filters = environ['tiddlyweb.filters'] if method_name: if not store_list: store_list = getattr(store, method_name) if not serializer_list: serializer_list = getattr(serializer, method_name) try: kept_entities = _filter_readable(environ, store_list(), filters) except FilterError, exc: raise HTTP400(exc) etag_string = '"%s:%s"' % (kept_entities.hexdigest(), sha(mime_type).hexdigest()) check_incoming_etag(environ, etag_string) try: output = serializer_list(kept_entities) except NoSerializationError: raise HTTP415('Content type not supported: %s' % mime_type) start_response("200 OK", [('Content-Type', mime_type), ('Vary', 'Accept'), ('Cache-Control', 'no-cache'), ('Etag', etag_string)]) if isinstance(output, basestring): return [output] else: return output