промежуточное ПО aiohttp и обновление URL-адреса для запроса

Я ищу помощь с промежуточным программным обеспечением aiohttp, над которым я работаю, которое автоматически добавит конечные косые черты к uri, если он отсутствует. Aiohttp требует, чтобы при определении URL-адреса вы определяли два маршрута для каждого пути в вашем списке маршрутов, один с завершающей косой чертой, а другой без. У них есть пример промежуточного программного обеспечения, которое решает эту проблему, определяя, не заканчивается ли uri на /, и добавляя его, если нет, но затем они используют перенаправление http 302, чтобы сообщить клиенту перейти на новый uri. В противном случае относительный uri, такой как /endpoint, будет 404, а /endpoint/ будет работать.

Это их промежуточное ПО:
https://github.com/aio-libs/aiohttp/blob/master/aiohttp/web_middlewares.py

Используя их промежуточное ПО в качестве основы, я пытаюсь сделать то же самое, но без перенаправления на стороне клиента. Я хочу, чтобы обработка была только на сервере. Моя текущая попытка для этого показана ниже и, кажется, обновляет запрос в полете, но я все еще получаю 404:

from aiohttp.web_urldispatcher import SystemRoute

def middleware(f):
    f.__middleware_version__ = 1
    return f

def trailing_slashes():
    @middleware
    async def impl(request, handler):
        if isinstance(request.match_info.route, SystemRoute):
            rel_url = str(request.rel_url)
            if '?' in rel_url:
                path, query = rel_url.split('?', 1)
                query = f'?{query}'
            else:
                path = rel_url
                query = ''
            if not path.endswith('/'):
                rel_url = f'{path}/{query}'
                request = request.clone(rel_url=rel_url)

        return await handler(request)

    return impl

Это класс, который реализует промежуточное ПО и иллюстрирует проблему.

from aiohttp import web
import slashes_mw

class ClassName(object):
    def __init__(self):
        self.app = web.Application(middlewares=[slashes_mw.trailing_slashes()])
        self.app.add_routes(self.get_routes())
        web.run_app(self.app, port=80, host='0.0.0.0')

    def get_routes(self):
        return [
            web.get('/', self.handler),
            web.get('/{name}/', self.handler)
        ]

    def handler(self, request):
        return web.Response(text='hello')

ClassName()

Есть идеи? Спасибо за вашу помощь.


person jerblack    schedule 21.06.2018    source источник


Ответы (1)


Я думаю, что подход с перенаправлением, который они предлагают, вполне правильный, так как маршруты просто не совпадают. Но вы можете попробовать просто зарегистрировать и вторую «версию» маршрута:

def get_routes(self):
    return [
        web.get('/', self.handler),
        web.get('/{name}/', self.handler),
        web.get('/{name}', self.handler)
    ]

Это должно решить вашу проблему на стороне сервера (НЕ ПРОВЕРЕНО).

Насколько я понимаю, ваш подход не работает, потому что конкретный обработчик выбирается ДО вызова различных промежуточных программ. Если вы вызываете функцию обработчика в промежуточном программном обеспечении, поиск «маршрутизации» больше не выполняется. По крайней мере, я так понимаю их документацию: https://docs.aiohttp.org/en/stable/web_advanced.html#middlewares

Также может быть интересно: https://docs.aiohttp.org/en/stable/web_quickstart.html#variable-resources

person sidi7    schedule 11.06.2020