[英]Flask not processing other HTTP requests after Chrome browser accesses the web-site
問題陳述:當我嘗試從Chrome瀏覽器訪問不存在的文件后,我在Flask上的Web服務器未處理HTTP請求。 當Chrome關閉或訪問確實存在的頁面時,積壓的HTTP請求將立即得到處理。
影響: Web服務器可用性很差。
問題:為什么會發生這種情況,以及如何在不以線程模式運行Flask的情況下進行修復?
我在網上找到的最近的帖子是:github.com/pallets/flask/issues/2188,但是找不到完全相同的問題和解決方案。 期待您的想法-非常感謝您的幫助!
主要假設: Chrome無法讀取404響應的所有內容,而Flask正在等待讀取所有內容
細節:
重現此問題的步驟:
1)運行最小的Flask應用程序( http://flask.pocoo.org/docs/0.12/quickstart/ ):
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
app.run()
2)確認您在瀏覽器或curl中收到“ Hello world”響應:
curl -v本地主機:5000 /
3)在Chrome瀏覽器中進入localhost:5000 / page,這表明筆記主義者在瀏覽器中觀察到“未找到”錯誤
4)重復curl -v localhost:5000 /命令
觀察已建立連接,但未收到響應,例如:
curl -v localhost:5000 / *正在嘗試:: 1 ... *連接失敗*連接到:: 1端口5000失敗:連接被拒絕*正在嘗試127.0.0.1 ... *已連接到localhost(127.0.0.1)端口5000( #0)
GET / HTTP / 1.1主機:localhost:5000用戶代理:curl / 7.49.0接受: /
5)在Chrome中轉到存在的頁面或關閉Chrome
觀察對卷曲的即時反應:
- HTTP 1.0,假定在正文之后關閉<HTTP / 1.0 200 OK <Content-Type:text / html; charset = utf-8 <Content-Length:13 <服務器:Werkzeug / 0.11.10 Python / 3.5.1 <日期:Tue,28 Feb 2017 21:44:20 GMT <
- 正在關閉連接0您好,世界!
重現此問題可能需要進行多種嘗試。 通常發生> 10次中的8次
其他信息:
1)代替curl,我可以使用Safari或telnet或python腳本-同樣的問題
2)Safari不會造成問題,Chrome會解決
3)嘗試通過發送與Chrome完全相同的http請求來模仿Chrome,但無法重現該問題。 Chrome可能會做其他事情。
4)當我在線程模式下運行Flask(使用不同的線程處理每個請求)時,問題就消失了。
5)版本:
Chrome版本56.0.2924.87(64位)
Python 3.5.2 | Anaconda 4.1.1(64位)| (默認,2016年7月2日,17:53:06)[Linux上的[GCC 4.4.7 20120313(Red Hat 4.4.7-1)]
燒瓶。 版本 “ 0.11.1”
6)AWS Ubuntu生產服務器計算機上也復制了該問題
7)嘗試在404 HTTP響應中發送自定義標頭,但沒有運氣
@app.errorhandler(404)
def page_not_found(e):
# return render_template('404.html'), 404
resp = make_response(render_template('404.html'), 404)
# resp.headers['Connection'] = 'close'
resp.headers['Cache-Control'] = 'no-cache, no-store'
return resp
更新
只要Chrome發出正常的http請求,我就可以重現該問題而不會出現404錯誤。 在Flask日志中沒有觀察到錯誤。
另一件有趣的事情-如果在Chrome瀏覽器中使用隱身窗口,則不會出現此問題。 但是,在正常模式下清除Chrome緩存並不能解決問題。
啟用線程。
app.run(host='0.0.0.0', port=80, debug=True, threaded=True)
TL; DR
該問題仍然有效。 啟用頁面預取功能后,Chrome似乎不會關閉連接,它會阻止服務器的執行,從而阻止后續請求的處理。
就我而言,這個問題甚至更嚴重,因為基於Android的手機也使用此預取功能並獲得相同的結果,因此我無法更改每個客戶端的設置。
我的解決方案/解決方法是在基礎的werkzeug
服務器( https://werkzeug.palletsprojects.com/en/0.16.x/serving/#werkzeug.serving.run_simple )中啟用threading
選項。 當然,它在服務器端占用的資源更多,但是它使我們可以在不阻止其他請求的情況下,將不良行為的請求/客戶端分離到單獨的線程中。
if __name__ == '__main__':
logger.info('starting web server life cycle')
app.run(host='0.0.0.0', port=80, debug=True, threaded=True)
我還檢查了請求處理是否正確完成,至少在Flask方面如此。 因此,問題必須出在Chrome /其他客戶端或基礎的werkzeug
服務器中。
@app.before_request
def filter_prefetch():
logger.debug("before request")
logger.debug(request.headers)
# uncomment these to filter Chrome specific prefetch requests.
# if 'Purpose' in request.headers and request.headers.get('Purpose') == 'prefetch':
# logger.debug("prefetch requests are not allowed")
# return '', status.HTTP_403_FORBIDDEN
@app.after_request
def debug_after(response):
logger.debug("after request")
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "0"
response.headers['Cache-Control'] = 'public, max-age=0'
response.headers['Connection'] = 'close'
return response
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.