Nginx反向代理多个应用时,通过BluePring使Flask支持二级路径(URL前缀)
1. 預期
最近陸續基于Nginx,完成了三個應用的部署:
- 應用A:《在Ngnix上部署Flask應用》
- 應用B:《PaddleOCR加載chinese_ocr_db_crnn_modile模型進行中英文混合預測(Http服務)實踐》
- 應用C:《php web server部署(PHP+Nginx+Redis+MySQL)》
理所當然冒出來一個想法就是把它們一并啟起來,而且云服務器上除了http的80和https的443以外,不要增加更多的端口。預期的效果如下:
例如,輸入帶SSL的URL地址:https://127.0.0.1,打開這樣一個導航頁面:
點擊“微信小應用服務”,即跳轉到帶SSL的URL地址:https://127.0.0.1/uu,打開應用A的頁面:
點擊“微信小應用服務”,即跳轉到帶SSL的URL地址:https://127.0.0.1/uu/ocr,打開應用B的頁面:
點擊“微信小應用服務”,即跳轉到不帶SSL的URL地址:http://127.0.0.1,打開應用C的頁面:
2. 配置
雖然應用A和B實際上是同一個Flask應用,不過在A的系列頁面中沒有指向B的鏈接,所以可以認為在“應用層面”上是兩個應用。不過不管是一個還是兩個,并不影響本文的重點:
本文的重點是:上面的想法理論上非常簡單,這正是Nginx反向代理的長項,只要在nginx.conf配置文件中設置多個location塊,分別指向不同URL前綴就可以了。
ngnix.conf配置如圖:
配置文件中添加了“add_header X-debug-message”,這樣可以方便的在瀏覽器控制臺看到我們走的是哪一條配置。如下圖所示:
3. 問題
然而實際部署起來還是遇到了一些困難,主要是無論是應用A和應用B,只要 location 不指向 / ,就無法在Flask中定位出正確的路由。以應用B為例,Nginx傳給后臺Flask的URL是:https://127.0.0.1/uu/ocr,但是Flask中的路由無法處理多出來的/uu
# OCR測試 @webapp.route('/ocr', methods=['POST', 'GET']) def ocr():basepath = os.path.dirname(__file__) # 當前文件所在路徑print(request.method)if request.method == 'POST':f = request.files['file']upload_path = os.path.join(basepath, 'static/uploads', secure_filename(f.filename)) # 注意:沒有的文件夾要先創建f.save(upload_path)return redirect(url_for('profile.ocr_result', pic_name=f.filename))else:return render_template('ocr.html')當然將所有路由標簽都加上前綴也能算是一種“笨辦法”,正道還是由Flask的BluePrint來解決。
4. 用BluePrint實現URL前綴功能
先給出一個最簡單的bp例子程序:
# 使用藍圖建立統一路由前綴,便于nginx部署多應用 # 通常這句話寫在routes.py中 bp = Blueprint('blueprint', __name__, url_prefix='/uu/vv', static_folder='', static_url_path='')# 用藍圖進行路由標記 @bp.route("/") def index_page():return "This is website root"# 用藍圖進行路由標記 @bp.route("/about") def about_page():return "This is a website about page"app = Flask(__name__) # 應用注冊藍圖 # 通常這句話寫在__init__.py中 app.register_blueprint(bp)上面這個簡單的例子可以正常運行,但是在Flask的項目中,需要考慮到有SQLAlchemy的數據庫模塊,還有LoginManager用戶登錄模塊,很容易引起循環import。所以在實際使用的時候,需要考慮將這些公共組件進行模塊化處理。
5. 用BluePrint將程序中的公共組件模塊化
對于 SQLAlchemy:
原本是在 __init__.py 中同時定義 db 并與 webapp 關聯:webapp.SQLAlchemy(db)。但是這樣會造成在 routes.py 中from app import db,同時又在 __init__.py 中from app.routes import bp,這樣就造成了循環導入。
可以改為在 models.py 中定義db = SQLAlchemy(),在 __init__.py 中通過 db.init_app(webapp) 進行 db 與 webapp 關聯。在 routes.py 和 __init__.py 中from app.models import db。
對于 LoginManager:
原本是在 __init__.py 中同時定義 login 并與 webapp 關聯:webapp.LoginManager(login)。
可以改為在 models.py 中定義 login = LoginManager() ,在 __init__.py 中from app.models import login,并通過 login.init_app(webapp) 進行 login 與 webapp 關聯。
6. url_for處理
在后臺python代碼,和html模板文件中的所有 url_for(function_name),全部需要改成 url_for(bp.function_name)
7. 靜態資源處理
以為一切妥當以后,發現靜態資源訪問不了。查了Blueprint的構造函數,發現參數static_folder和static_url_path的缺省值都是None,改成空字符串’'后,又可以看到靜態資源了。
所有的源碼在這里,歡迎下載并提出寶貴意見 : - )
【參考資料】
《如何為所有Flask路由添加前綴?》
《python flask使用blueprint》
《flask+SQLAlchemy使用blueprint模塊化》
《有關flask的static文件夾,如何設置在blueprint的根目錄下呢》
總結
以上是生活随笔為你收集整理的Nginx反向代理多个应用时,通过BluePring使Flask支持二级路径(URL前缀)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows平台:Nginx+Torn
- 下一篇: Vue.js教程学习笔记