Вернуть запрос. Объект ответа из Flask
Я пытаюсь создать простой прокси-сервер, используя флажок и запросы. Код выглядит следующим образом:
@app.route('/es/<string:index>/<string:type>/<string:id>',
methods=['GET', 'POST', 'PUT']):
def es(index, type, id):
elasticsearch = find_out_where_elasticsearch_lives()
# also handle some authentication
url = '%s%s%s%s' % (elasticsearch, index, type, id)
esreq = requests.Request(method=request.method, url=url,
headers=request.headers, data=request.data)
resp = requests.Session().send(esreq.prepare())
return resp.text
Это работает, за исключением того, что он теряет код статуса из Elasticsearch. Я попытался вернуть resp
(a requests.models.Response
) напрямую, но это не удается с помощью
TypeError: 'Response' object is not callable
Есть ли другой, простой способ вернуть requests.models.Response
из фляги?
Ответы
Ответ 1
Хорошо, нашел:
Если кортеж возвращен, элементы в кортеже могут предоставить дополнительную информацию. Такие кортежи должны быть в форме (ответ, статус, заголовки), где по крайней мере один элемент должен быть в кортеже. Значение статуса переопределит код состояния, а заголовки могут быть списком или словарем дополнительных значений заголовка.
(Документы флажков.)
Итак,
return (resp.text, resp.status_code, resp.headers.items())
похоже, делает трюк.
Ответ 2
Использование свойства text
или content
объекта Response
не будет работать, если сервер возвращает закодированные данные (например, content-encoding: gzip
) и вы возвращаете заголовки без изменений. Это происходит из-за того, что text
и content
были декодированы, поэтому между кодировкой, сообщаемой в заголовке, и фактическим кодированием будет несоответствие.
Согласно документации:
В редком случае, когда вы хотите получить необработанный ответ сокета от сервера, вы можете получить доступ к r.raw
. Если вы хотите сделать это, убедитесь, что вы установили stream=True
в своем первоначальном запросе.
а также
Response.raw
- это необработанный поток байтов - он не преобразует содержимое ответа.
Итак, для gzipped-данных тоже работает следующее:
esreq = requests.Request(method=request.method, url=url,
headers=request.headers, data=request.data)
resp = requests.Session().send(esreq.prepare(), stream=True)
return resp.raw.read(), resp.status_code, resp.headers.items()
Если вы используете метод ярлыка, такой как get
, он просто:
resp = requests.get(url, stream=True)
return resp.raw.read(), resp.status_code, resp.headers.items()
Ответ 3
Я столкнулся с тем же сценарием, за исключением того, что в моем случае мои запросы .models.Response содержали вложение. Вот как я заработал:
return send_file (BytesIO (result.content), mimetype = result.headers ['Content-Type'], as_attachment = True)