问题描述

在成功的部署Python flask应用到App Service (Windows)后,如果需要把当前项目(如:hiflask)作为一个子项目(子站点),把web.config文件从wwwroot中移动到项目文件夹中。访问时,确遇见了404 Not Found的错误。

 

 

 查看flask项目的启动日志,可以看见项目启动已经成功。但是为什么请求一直都是404的问题呢?

2021-09-10 05:29:58.224796: wfastcgi.py will restart when files in D:\home\site\wwwroot\hiflask\ are changed: .*((\.py)|(\.config))$

2021-09-10 05:29:58.240445: wfastcgi.py 3.0.0 initialized

 

问题解决

在搜索 flask return 404问题后,发现是因为 URL前缀(prefixed )的问题。因为当前的flask应用访问路径不再是根目录(/),而是(/hiflask)。 所以需要 flask项目中使用 中间件 来处理 url前缀的问题。

原文内容为:https://stackoverflow.com/questions/18967441/add-a-prefix-to-all-flask-routes/36033627#36033627

You have to do is to write a middleware to make the following changes:

modify PATH_INFO to handle the prefixed url.

modify SCRIPT_NAME to generate the prefixed url.

Like this:

class PrefixMiddleware(object):

def __init__(self, app, prefix=''):

self.app = app

self.prefix = prefix

def __call__(self, environ, start_response):

if environ['PATH_INFO'].startswith(self.prefix):

environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):]

environ['SCRIPT_NAME'] = self.prefix

return self.app(environ, start_response)

else:

start_response('404', [('Content-Type', 'text/plain')])

return ["This url does not belong to the app.".encode()]

Wrap your app with the middleware, like this:

from flask import Flask, url_for

app = Flask(__name__)

app.debug = True

app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix='/foo')

@app.route('/bar')

def bar():

return "The URL for this page is {}".format(url_for('bar'))

if __name__ == '__main__':

app.run('0.0.0.0', 9010)

 

Visit http://localhost:9010/foo/bar,

You will get the right result: The URL for this page is /foo/bar

而在App Service中的解决方式就是添加了 PrefixMiddleware,并指定prefix为 /hiflask 。 附上完成的hiflask/app.py 代码和web.config内容。

hiflask/app.py

from flask import Flask

from datetime import datetime

from flask import render_template

import re

class PrefixMiddleware(object):

def __init__(self, app, prefix=''):

self.app = app

self.prefix = prefix

def __call__(self, environ, start_response):

if environ['PATH_INFO'].startswith(self.prefix):

environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):]

environ['SCRIPT_NAME'] = self.prefix

return self.app(environ, start_response)

else:

start_response('404', [('Content-Type', 'text/plain')])

return ["This url does not belong to the app.".encode()]

#if __name__ =="__name__"

app = Flask(__name__)

app.debug = True

app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix='/hiflask')

# @app.route("/")

# def home():

# return "Hello, Flask!"

print("flask applicaiton started and running..." +datetime.now().strftime("%m/%d/%Y, %H:%M:%S"))

# Replace the existing home function with the one below

@app.route("/")

def home():

return render_template("home.html")

# New functions

@app.route("/about/")

def about():

return render_template("about.html")

@app.route("/contact/")

def contact():

return render_template("contact.html")

@app.route("/hello/")

@app.route("/hello/")

def hello_there(name = None):

return render_template(

"hello_there.html",

name=name,

date=datetime.now()

)

@app.route("/api/data")

def get_data():

return app.send_static_file("data.json")

if __name__ == '__main__':

app.run(debug=True)

 

hiflask/web.config

最终效果(作为子项目部署完成成功,所以一个app service就可以部署多个站点)

提醒一点:App Service中如果要部署多站点,需要在Configration 中配置 Virtual Applications。

 

 

 参考资料:

https://stackoverflow.com/questions/18967441/add-a-prefix-to-all-flask-routes/36033627#36033627

https://www.cnblogs.com/lulight/p/15220297.html

https://www.cnblogs.com/lulight/p/15227028.html

 

精彩文章

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。