def collection_get(self): """Model ``GET`` endpoint: retrieve multiple records. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPNotModified` if ``If-None-Match`` header is provided and collection not modified in the interim. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPPreconditionFailed` if ``If-Match`` header is provided and collection modified in the iterim. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPBadRequest` if filters or sorting are invalid. """ self._add_timestamp_header(self.request.response) self._add_cache_header(self.request.response) self._raise_304_if_not_modified() self._raise_412_if_modified() headers = self.request.response.headers filters = self._extract_filters() limit = self._extract_limit() sorting = self._extract_sorting(limit) partial_fields = self._extract_partial_fields() filter_fields = [f.field for f in filters] include_deleted = self.model.modified_field in filter_fields pagination_rules, offset = self._extract_pagination_rules_from_token( limit, sorting) records, total_records = self.model.get_records( filters=filters, sorting=sorting, limit=limit, pagination_rules=pagination_rules, include_deleted=include_deleted) offset = offset + len(records) next_page = None if limit and len(records) == limit and offset < total_records: lastrecord = records[-1] next_page = self._next_page_url(sorting, limit, lastrecord, offset) headers['Next-Page'] = encode_header(next_page) if partial_fields: records = [ dict_subset(record, partial_fields) for record in records ] # Bind metric about response size. logger.bind(nb_records=len(records), limit=limit) headers['Total-Records'] = encode_header('%s' % total_records) return self.postprocess(records)
def collection_get(self): """Collection ``GET`` endpoint: retrieve multiple records. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPNotModified` if ``If-None-Match`` header is provided and collection not modified in the interim. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPPreconditionFailed` if ``If-Match`` header is provided and collection modified in the iterim. :raises: :exc:`~pyramid:pyramid.httpexceptions.HTTPBadRequest` if filters or sorting are invalid. """ self._add_timestamp_header(self.request.response) self._raise_304_if_not_modified() self._raise_412_if_modified() headers = self.request.response.headers filters = self._extract_filters() sorting = self._extract_sorting() limit = self._extract_limit() filter_fields = [f.field for f in filters] include_deleted = self.collection.modified_field in filter_fields pagination_rules = self._extract_pagination_rules_from_token( limit, sorting) records, total_records = self.collection.get_records( filters=filters, sorting=sorting, limit=limit, pagination_rules=pagination_rules, include_deleted=include_deleted) next_page = None if limit and len(records) == limit and total_records > limit: next_page = self._next_page_url(sorting, limit, records[-1]) headers['Next-Page'] = encode_header(next_page) # Bind metric about response size. logger.bind(nb_records=len(records), limit=limit) headers['Total-Records'] = encode_header('%s' % total_records) body = { 'data': records, } return body
def service_unavailable(response, request): if response.content_type != 'application/json': error_msg = "Service unavailable due to high load, please retry later." response = http_error(response, errno=ERRORS.BACKEND, message=error_msg) retry_after = request.registry.settings['retry_after_seconds'] response.headers["Retry-After"] = encode_header('%s' % retry_after) return reapply_cors(request, response)
def _add_timestamp_header(self, response, timestamp=None): """Add current timestamp in response headers, when request comes in. """ if timestamp is None: timestamp = self.timestamp # Pyramid takes care of converting. response.last_modified = timestamp / 1000.0 # Return timestamp as ETag. response.headers['ETag'] = encode_header('"%s"' % timestamp)
def service_unavailable(context, request): error_msg = "Service unavailable due to high load, please retry later." response = http_error(httpexceptions.HTTPServiceUnavailable(), errno=ERRORS.BACKEND, message=error_msg) retry_after = request.registry.settings['cliquet.retry_after_seconds'] response.headers["Retry-After"] = encode_header('%s' % retry_after) return reapply_cors(request, response)
def service_unavailable(response, request): if response.content_type != 'application/json': error_msg = ("Service temporary unavailable " "due to overloading or maintenance, please retry later.") response = http_error(response, errno=ERRORS.BACKEND, message=error_msg) retry_after = request.registry.settings['retry_after_seconds'] response.headers["Retry-After"] = encode_header('%s' % retry_after) return reapply_cors(request, response)
def send_alert(request, message=None, url=None, code='soft-eol'): """Helper to add an Alert header to the response. :param code: The type of error 'soft-eol', 'hard-eol' :param message: The description message. :param url: The URL for more information, default to the documentation url. """ if url is None: url = request.registry.settings['project_docs'] request.response.headers['Alert'] = encode_header(json.dumps({ 'code': code, 'message': message, 'url': url }))
def upload(self, files=None, params=[], headers={}, status=None, randomize=True): files = files or self.default_files headers = headers or self.headers.copy() content_type, body = self.app.encode_multipart(params, files) headers['Content-Type'] = cliquet_utils.encode_header(content_type) if not randomize: endpoint_url = self.endpoint_uri + '?randomize=false' else: endpoint_url = self.endpoint_uri resp = self.app.post(endpoint_url, body, headers=headers, status=status) if 200 <= resp.status_code < 300: self._add_to_cleanup(resp.json) return resp
def test_returns_a_string_if_passed_bytes(self): entry = 'Toto'.encode('utf-8') value = encode_header(entry) self.assertEqual(type(value), str)
def test_returns_a_string_if_passed_unicode_with_encoding(self): entry = six.text_type('Rémy') value = encode_header(entry, 'latin-1') self.assertEqual(type(value), str)
def test_returns_a_string_if_passed_bytes_and_encoding(self): entry = 'Rémy'.encode('latin-1') value = encode_header(entry, 'latin-1') self.assertEqual(type(value), str)
def test_returns_a_string_if_passed_a_string(self): entry = str('Toto') value = encode_header(entry) self.assertEqual(entry, value) self.assertEqual(type(value), str)
def on_new_response(event): # Add backoff in response headers. backoff = config.registry.settings['backoff'] if backoff is not None: backoff = utils.encode_header('%s' % backoff) event.response.headers['Backoff'] = backoff
def test_returns_a_string_if_passed_bytes_and_encoding(self): entry = "Rémy".encode("latin-1") value = encode_header(entry, "latin-1") self.assertEqual(type(value), str)
def test_returns_a_string_if_passed_unicode(self): entry = six.text_type("Rémy") value = encode_header(entry) self.assertEqual(type(value), str)
def on_new_response(event): # Add backoff in response headers. backoff = config.registry.settings["backoff"] if backoff is not None: backoff = utils.encode_header("%s" % backoff) event.response.headers["Backoff"] = backoff