Select a suitable handler to handle the request.

    Returns a (handler, vary) tuple, where handler is a handler_metadata tuple
    and vary is a set containing header names that were used during content
    negotiation and that should be included in the 'Vary' header of the
    outgoing response.

    When no suitable handler exists, raises NotFound, MethodNotAllowed,
    UnsupportedMediaType or NotAcceptable.

def resolve_handler(request, view_handlers):
    """Select a suitable handler to handle the request.

    Returns a (handler, vary) tuple, where handler is a handler_metadata tuple
    and vary is a set containing header names that were used during content
    negotiation and that should be included in the 'Vary' header of the
    outgoing response.

    When no suitable handler exists, raises NotFound, MethodNotAllowed,
    UnsupportedMediaType or NotAcceptable.
    """
    view = None
    if request._context:  # Allow context to be missing for easier testing
        route_name = request._context[-1].route.name
        if route_name and VIEW_SEPARATOR in route_name:
            view = route_name.split(VIEW_SEPARATOR, 1)[1] or None

    if view not in view_handlers:
        raise NotFound

    method_handlers = view_handlers[view]

    verb = request.method
    if verb not in method_handlers:
        if verb == 'HEAD' and 'GET' in method_handlers:
            verb = 'GET'
        else:
            allowed_methods = set(method_handlers.keys())
            if 'HEAD' not in allowed_methods and 'GET' in allowed_methods:
                allowed_methods.add('HEAD')
            allow = ', '.join(sorted(allowed_methods))
            raise MethodNotAllowed(allow=allow)

    handlers = method_handlers[verb]
    vary = set()
    if len(set(h.provides for h in handlers if h.provides is not None)) > 1:
        vary.add('Accept')
    if len(set(h.accepts for h in handlers)) > 1:
        vary.add('Content-Type')

    content_type = request.content_type
    if content_type:
        handlers = negotiate_content_type(content_type, handlers)
        if not handlers:
            raise UnsupportedMediaType

    accept = request.headers.get('Accept')
    if accept:
        handlers = negotiate_accept(accept, handlers)
        if not handlers:
            raise NotAcceptable

    return handlers[0], vary