Направляйте запросы на основе заголовка Accept в веб-фреймворках Python

У меня есть некоторый опыт работы с различными веб-фреймворками (Django, web.py, Pyramid и CherryPy), и мне интересно, в какой из них будет проще и, надеюсь, чище реализовать диспетчер маршрутов для другого "представления / обработчика" на основе заголовок "Принять" и метод HTTP, например:

Accept: application/json
POST /post/

обрабатывается иначе, чем:

Accept: text/html
POST /post/

Таким образом, запрос направляется в конкретное представление соответствующего обработчика MIME "application/json" и HTTP-метода "POST".

Я знаю, как реализовать нечто подобное в CherryPy, но я теряю использование инструментов CherryPy для внутреннего перенаправления запроса, потому что я вызываю определенный метод напрямую, а не автоматически из диспетчера. Другой вариант - реализовать новый диспетчер с нуля, но это последний вариант.

Я знаю об альтернативе использования расширений в URL, как /post.json или же /post/.json, но я хочу сохранить тот же URL?

3 ответа

Решение

Если все, что вам нужно, это одна структура, которая может сделать это легко, тогда используйте pyramid,

Определения представления Pyramid создаются с использованием предикатов, а не только маршрутов, и представление соответствует, только если все предикаты совпадают. Одним из таких предикатов является accept предикат, который делает именно то, что вы хотите; сделать переключение вида в зависимости от Accept заголовок легко и просто:

from pyramid.view import view_config

@view_config(route_name='some_api_name', request_method='POST', accept='application/json')
def handle_someapi_json(request):
    # return JSON

@view_config(route_name='some_api_name', request_method='POST', accept='text/html')
def handle_someapi_html(request):
    # return HTML

Мне нужно было сделать это в Django, и поэтому я написал часть промежуточного программного обеспечения, чтобы сделать это возможным: http://baltaks.com/2013/01/route-requests-based-on-the-http-accept-header-in-django

Вот код:

# A simple middleware component that lets you use a single Django
# instance to serve multiple versions of your app, chosen by the client
# using the HTTP Accept header.
# In your settings.py, map a value you're looking for in the Accept header
# to a urls.py file.
# HTTP_HEADER_ROUTING_MIDDLEWARE_URLCONF_MAP = {
#     u'application/vnd.api-name.v1': 'app.urls_v1'
# }

from django.conf import settings

class HTTPHeaderRoutingMiddleware:

    def process_request(self, request):
        try:
            for content_type in settings.HTTP_HEADER_ROUTING_MIDDLEWARE_URLCONF_MAP:
                if (request.META['HTTP_ACCEPT'].find(content_type) != -1):
                    request.urlconf = settings.HTTP_HEADER_ROUTING_MIDDLEWARE_URLCONF_MAP[content_type]
        except KeyError:
            pass # use default urlconf (settings.ROOT_URLCONF)

    def process_response(self, request, response):
        return response

Я не совсем уверен, что вы подразумеваете под "внутренним перенаправлением", но если вы посмотрите на код, вы увидите, что tools.accept - действительно тонкая оболочка для lib.cptools.accept, которую вы можете легко вызвать из своего собственного кода., Передайте ему список типов контента, которые ваш сервер может отправить, и он скажет вам, какой клиент предпочитает, или выдаст 406, если типы, которые вы отправляете, и типы, которые принимает клиент, не пересекаются.

Другие вопросы по тегам