chapeau/kepi/tophat_ui/view_for_mimetype.py

91 wiersze
2.5 KiB
Python

# view_for_mimetype.py
#
# Part of kepi.
# Copyright (c) 2018-2020 Marnanel Thurman.
# Licensed under the GNU Public License v2.
#
# This might work better as a standalone module,
# separate from kepi?
import logging
logger = logging.getLogger(name='kepi')
from kepi.tophat_ui.parse_accept import parse_accept_header
from django.http import HttpResponse
def view_for_mimetype(
views,
default = None,
):
"""
Returns a Django view function which can route requests
to other view functions based on the incoming Accept header.
Params:
views - a list of (type, subtype, view) triplets
e.g. ('text', 'html', HelloWorldView)
default - the default to return if the Accept header
can't otherwise be satisfied.
If you don't give a default, the view function returns
a new HttpResponse with status_code==406, i.e. "Not Acceptable".
See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406
As a special case, if request is None, returns the list of views.
A default value will be at the end, with type and subtype set to None.
"""
def _view_for_mimetype_inner(
request,
*args, **kwargs,
):
if request is None:
result = views.copy()
if default is not None:
result.append((None, None, default))
return result
accept_header = request.headers.get('Accept', '')
accept_parsed = parse_accept_header(accept_header)
logger.debug("Accept=%s -> %s", accept_header, accept_parsed)
logger.debug("Views: %s", views)
for want_type, want_subtype, params, q in accept_parsed:
for have_type, have_subtype, view in views:
if want_type != have_type:
continue
if want_subtype not in (have_subtype, '*'):
continue
logger.debug(' -- found %s/%s: %s',
have_type, have_subtype, view)
result = view(request,
*args, **kwargs,
)
return result
if default is not None:
logger.debug(' -- using default: %s',
view)
result = default(request,
*args, **kwargs,
)
return result
else:
logger.debug(' -- none found; 406')
# return 406 Not Acceptable
return HttpResponse(status=406)
return _view_for_mimetype_inner