• 【Azure 应用服务】Python flask 应用部署在Aure App Service中作为一个子项目时,解决遇见的404 Not Found问题


    问题描述

    在成功的部署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:homesitewwwroothiflask 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:

    1. modify PATH_INFO to handle the prefixed url.
    2. 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/<name>")
    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

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <appSettings>
        <add key="WSGI_HANDLER" value="app.app"/>
        <add key="PYTHONPATH" value="D:homesitewwwroothiflask"/>
        <add key="WSGI_LOG" value="D:homesitewwwroothiflaskhiflasklogs.log"/>
      </appSettings>
      <system.webServer>
        <handlers>
        <add name="PythonHandler" path="*" verb="*" modules="FastCgiModule" scriptProcessor="D:homepython364x64python.exe|D:homepython364x64wfastcgi.py" resourceType="Unspecified" requireAccess="Script"/>
        </handlers>
      </system.webServer>
    </configuration>

    最终效果(作为子项目部署完成成功,所以一个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

    当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。 云中,恰是如此!

  • 相关阅读:
    感想
    正则表达式
    推送、透传、MQ
    Spring集成Quartz定时任务 ---- 定时执行
    代码优化
    nginx配置详解、端口重定向和504
    JAVA实现EXCEL导出
    js 按需加载
    MyBatis使用(二)分页查询
    MyBatis使用(一)
  • 原文地址:https://www.cnblogs.com/lulight/p/15251312.html
Copyright © 2020-2023  润新知