Подтвердить что ты не робот

Проксирование на другой веб-сервис с помощью Flask

Я хочу прокси-запросы, сделанные в моем приложении Flask, другому веб-сервису, запущенному локально на машине. Я предпочел бы использовать Flask для этого, чем наш пример nginx более высокого уровня, чтобы мы могли повторно использовать существующую систему аутентификации, встроенную в наше приложение. Чем больше мы можем сохранить этот "единственный знак", тем лучше.

Есть ли для этого существующий модуль или другой код? Попытка подключить приложение "Флаш" к чему-то вроде httplib или urllib оказывается больной.

4b9b3361

Ответ 1

У меня есть реализация прокси-сервера с использованием httplib в приложении на основе Werkzeug (как и в вашем случае, мне нужно было использовать аутентификацию и авторизацию Webapp).

Хотя в документах Flask не указано, как обращаться к заголовкам HTTP, вы можете использовать request.headers (см. документация Werkzeug). Если вам не нужно изменять ответ, а заголовки, используемые прокси-сервером, предсказуемы, прокси-сервер является staightforward.

Обратите внимание, что если вам не нужно изменять ответ, вы должны использовать werkzeug.wsgi.wrap_file для переноса потока ответов httplib. Это позволяет передавать открытый файловый дескриптор OS-сервера на HTTP-сервер для оптимальной производительности.

Ответ 2

Я потратил много времени, работая над этим же, и в итоге нашел решение с использованием библиотеки запросов, которая, похоже, работает хорошо. Он даже обрабатывает установку нескольких файлов cookie в одном ответе, что потребовало нескольких исследований для выяснения. Здесь функция просмотра колбы:

from flask import request, Response
import requests

def _proxy(*args, **kwargs):
    resp = requests.request(
        method=request.method,
        url=request.url.replace('old-domain.com', 'new-domain.com'),
        headers={key: value for (key, value) in request.headers if key != 'Host'},
        data=request.get_data(),
        cookies=request.cookies,
        allow_redirects=False)

    excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
    headers = [(name, value) for (name, value) in resp.raw.headers.items()
               if name.lower() not in excluded_headers]

    response = Response(resp.content, resp.status_code, headers)
    return response

Ответ 3

Мой первоначальный план состоял в том, что публичный URL-адрес был чем-то вроде http://www.example.com/admin/myapp проксирования до http://myapp.internal.example.com/. Вниз этот путь ведет к безумию.

Большинство webapps, особенно самообслуживаемых, предполагают, что они будут работать в корне HTTP-сервера и делать такие вещи, как ссылки на другие файлы по абсолютному пути. Чтобы обойти это, вам нужно переписать URL-адреса повсеместно: заголовки местоположений и HTML, JavaScript и файлы CSS.

Я написал проект прокси-сервера Flask, который сделал это, и, хотя он работал достаточно хорошо для одного webapp, который я действительно хотел прокси, он не был устойчивым. Это был большой беспорядок регулярных выражений.

В конце концов, я настроил новый виртуальный хост в nginx и использовал его собственный прокси. Поскольку оба они находились в корневой части хоста, переписывание URL-адресов в основном было ненужным. (И то, что мало было необходимо, обрабатывался модуль прокси-сервера nginx.) Прокси-сервер webapp имеет свою собственную аутентификацию, которая сейчас достаточно хороша.