Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为所有管线添加前缀_Python_Routes_Flask - Fatal编程技术网

Python 为所有管线添加前缀

Python 为所有管线添加前缀,python,routes,flask,Python,Routes,Flask,我有一个前缀,我想添加到每个路由。现在,我在每个定义处为路由添加一个常量。有没有一种方法可以自动做到这一点 PREFIX = "/abc/123" @app.route(PREFIX + "/") def index_page(): return "This is a website about burritos" @app.route(PREFIX + "/about") def about_page(): return "This is a website about burri

我有一个前缀,我想添加到每个路由。现在,我在每个定义处为路由添加一个常量。有没有一种方法可以自动做到这一点

PREFIX = "/abc/123"

@app.route(PREFIX + "/")
def index_page():
  return "This is a website about burritos"

@app.route(PREFIX + "/about")
def about_page():
  return "This is a website about burritos"

答案取决于您如何为该应用程序提供服务

子组件安装在另一个WSGI容器内 假设您将在WSGI容器(mod_WSGI、uwsgi、gunicorn等)中运行此应用程序;您需要在该前缀处将应用程序作为WSGI容器的一个子部分实际装载(任何说WSGI的都可以),并将配置值设置为前缀:

app.config["APPLICATION_ROOT"] = "/abc/123"

@app.route("/")
def index():
    return "The URL for this page is {}".format(url_for("index"))

# Will return "The URL for this page is /abc/123/"
设置配置值只是将Flask的会话cookie限制为该URL前缀。Flask和Werkzeug出色的WSGI处理能力将为您自动处理所有其他内容

正确安装应用程序的示例 如果您不确定第一段的意思,请查看安装有烧瓶的示例应用程序:

from flask import Flask, url_for
from werkzeug.serving import run_simple
from werkzeug.wsgi import DispatcherMiddleware

app = Flask(__name__)
app.config['APPLICATION_ROOT'] = '/abc/123'

@app.route('/')
def index():
    return 'The URL for this page is {}'.format(url_for('index'))

def simple(env, resp):
    resp(b'200 OK', [(b'Content-Type', b'text/plain')])
    return [b'Hello WSGI World']

app.wsgi_app = DispatcherMiddleware(simple, {'/abc/123': app.wsgi_app})

if __name__ == '__main__':
    app.run('localhost', 5000)
将请求代理到应用程序 另一方面,如果您将在其WSGI容器的根目录下运行Flask应用程序,并将请求代理给它(例如,如果它是FastCGI'd to,或者如果nginx是
proxy\u pass
,将子端点的请求代理给您的独立
uwsgi
/
gevent
服务器,则您可以:

  • 使用一个蓝图,正如米格尔在书中指出的那样
  • 或者使用
    werkzeug
    中的
    DispatcherMiddleware
    (或
    PrefixMiddleware
    from)在您使用的独立WSGI服务器中分载您的应用程序。(请参阅上面正确分载您的应用程序以使用代码的示例)

您可以在蓝图中列出您的路线:

bp = Blueprint('burritos', __name__,
                        template_folder='templates')

@bp.route("/")
def index_page():
  return "This is a website about burritos"

@bp.route("/about")
def about_page():
  return "This is a website about burritos"
然后使用前缀向应用程序注册蓝图:

app = Flask(__name__)
app.register_blueprint(bp, url_prefix='/abc/123')

您应该注意,
应用程序\u ROOT
并非用于此目的

您所要做的就是编写一个中间件来进行以下更改:

  • 修改
    PATH\u INFO
    以处理带前缀的url
  • 修改
    SCRIPT\u NAME
    以生成带前缀的url
  • 像这样:

    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()]
    
    使用中间件包装您的应用程序,如下所示:

    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)
    
    from flask import Flask, Blueprint
    
    # Let's pretend module_blueprint defines a route, '/record/<id>/'
    from some_submodule.flask import module_blueprint
    
    app = Flask(__name__)
    app.config['APPLICATION_ROOT'] = '/api'
    app.register_blueprint(module_blueprint, url_prefix='/some_submodule')
    app.run()
    
    # I now would like to be able to get to my route via this url:
    # http://host:8080/api/some_submodule/record/1/
    
    app = Flask(__name__)
    app.route = prefix_route(app.route, '/your_prefix')
    
    from flask import Flask, url_for
    app = Flask(__name__)
    @app.route('/bar')
    def bar():
      return "The URL for this page is {}".format(url_for('bar'))
    # end def
    
    访问
    http://localhost:9010/foo/bar

    您将得到正确的结果:
    此页面的URL是/foo/bar

    如果需要,不要忘记设置cookie域


    这个解决方案是由给出的。
    应用程序\u ROOT
    不适合这个工作,尽管它看起来像是。它确实令人困惑。

    因此,我认为一个有效的答案是:前缀应该在开发完成时使用的实际服务器应用程序中配置。Apache、nginx等等

    但是,如果您希望在开发过程中在调试中运行Flask应用程序时使用此功能,请参阅

    Flask的
    调度终端软件
    去救援!
    我将把代码复制到这里供子孙后代使用:

    "Serve a Flask app on a sub-url during localhost development."
    
    from flask import Flask
    
    
    APPLICATION_ROOT = '/spam'
    
    
    app = Flask(__name__)
    app.config.from_object(__name__)  # I think this adds APPLICATION_ROOT
                                      # to the config - I'm not exactly sure how!
    # alternatively:
    # app.config['APPLICATION_ROOT'] = APPLICATION_ROOT
    
    
    @app.route('/')
    def index():
        return 'Hello, world!'
    
    
    if __name__ == '__main__':
        # Relevant documents:
        # http://werkzeug.pocoo.org/docs/middlewares/
        # http://flask.pocoo.org/docs/patterns/appdispatch/
        from werkzeug.serving import run_simple
        from werkzeug.wsgi import DispatcherMiddleware
        app.config['DEBUG'] = True
        # Load a dummy app at the root URL to give 404 errors.
        # Serve app at APPLICATION_ROOT for localhost development.
        application = DispatcherMiddleware(Flask('dummy_app'), {
            app.config['APPLICATION_ROOT']: app,
        })
        run_simple('localhost', 5000, application, use_reloader=True)
    
    现在,当作为独立的Flask应用程序运行上述代码时,
    http://localhost:5000/spam/
    将显示
    你好,世界!

    在对另一个答案的评论中,我表示我希望这样做:

    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)
    
    from flask import Flask, Blueprint
    
    # Let's pretend module_blueprint defines a route, '/record/<id>/'
    from some_submodule.flask import module_blueprint
    
    app = Flask(__name__)
    app.config['APPLICATION_ROOT'] = '/api'
    app.register_blueprint(module_blueprint, url_prefix='/some_submodule')
    app.run()
    
    # I now would like to be able to get to my route via this url:
    # http://host:8080/api/some_submodule/record/1/
    
    app = Flask(__name__)
    app.route = prefix_route(app.route, '/your_prefix')
    
    from flask import Flask, url_for
    app = Flask(__name__)
    @app.route('/bar')
    def bar():
      return "The URL for this page is {}".format(url_for('bar'))
    # end def
    

    这更像是python的答案,而不是Flask/werkzeug的答案;但它很简单,也很有效

    如果像我一样,您希望您的应用程序设置(从
    .ini
    文件加载)也包含Flask应用程序的前缀(因此,不要在部署期间设置值,而是在运行时设置值),您可以选择以下选项:

    def prefix_route(route_function, prefix='', mask='{0}{1}'):
      '''
        Defines a new route function with a prefix.
        The mask argument is a `format string` formatted with, in that order:
          prefix, route
      '''
      def newroute(route, *args, **kwargs):
        '''New function to prefix the route'''
        return route_function(mask.format(prefix, route), *args, **kwargs)
      return newroute
    
    可以说,这有点老土,它依赖于Flask route函数需要一个
    route
    作为第一个位置参数这一事实

    您可以这样使用它:

    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)
    
    from flask import Flask, Blueprint
    
    # Let's pretend module_blueprint defines a route, '/record/<id>/'
    from some_submodule.flask import module_blueprint
    
    app = Flask(__name__)
    app.config['APPLICATION_ROOT'] = '/api'
    app.register_blueprint(module_blueprint, url_prefix='/some_submodule')
    app.run()
    
    # I now would like to be able to get to my route via this url:
    # http://host:8080/api/some_submodule/record/1/
    
    app = Flask(__name__)
    app.route = prefix_route(app.route, '/your_prefix')
    
    from flask import Flask, url_for
    app = Flask(__name__)
    @app.route('/bar')
    def bar():
      return "The URL for this page is {}".format(url_for('bar'))
    # end def
    

    注意:在前缀中使用变量(例如,将其设置为
    /
    ),然后在您用
    @app.route(…)
    修饰的函数中处理此前缀,这是毫无意义的。如果这样做,您显然必须在修饰的函数中声明
    prefix
    参数。此外,您可能希望根据某些规则检查提交的前缀,如果检查失败,则返回404。为了避免404自定义重新实现,请从werkzeug导入
    。异常导入NotFound
    ,如果检查失败,则导入
    提升NotFound()

    我需要类似的所谓“上下文根目录”.I使用WSGIScriptAlias在/etc/httpd/conf.d/下的conf文件中执行此操作:

    myapp.conf:
    
    WSGIScriptAlias/myapp/home//myapp/wsgi.py
    命令拒绝,允许
    通融
    
    现在我可以通过以下方式访问我的应用程序:


    参见指南-

    另一种完全不同的方式是在
    uwsgi
    中使用挂载点

    从文档中获取关于()的信息

    uwsgi.ini
    中添加

    [uwsgi]
    mount = /foo=main.py
    manage-script-name = true
    
    # also stuff which is not relevant for this, but included for completeness sake:    
    module = main
    callable = app
    socket = /tmp/uwsgi.sock
    
    如果不调用文件
    main.py
    ,则需要同时更改
    装载
    模块

    您的
    main.py
    可能如下所示:

    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)
    
    from flask import Flask, Blueprint
    
    # Let's pretend module_blueprint defines a route, '/record/<id>/'
    from some_submodule.flask import module_blueprint
    
    app = Flask(__name__)
    app.config['APPLICATION_ROOT'] = '/api'
    app.register_blueprint(module_blueprint, url_prefix='/some_submodule')
    app.run()
    
    # I now would like to be able to get to my route via this url:
    # http://host:8080/api/some_submodule/record/1/
    
    app = Flask(__name__)
    app.route = prefix_route(app.route, '/your_prefix')
    
    from flask import Flask, url_for
    app = Flask(__name__)
    @app.route('/bar')
    def bar():
      return "The URL for this page is {}".format(url_for('bar'))
    # end def
    
    和nginx配置(同样为了完整性):


    现在调用
    example.com/foo/bar
    将显示flask的
    url\u为('bar')
    返回的
    /foo/bar
    ,因为它会自动调整。这样你的链接将不会出现前缀问题。

    我的解决方案,其中flask和PHP应用程序共存 nginx和PHP5.6

    将Flask保存在root目录中,将PHP保存在子目录中

    sudo vi/etc/php/5.6/fpm/php.ini
    添加1行

    cgi.fix\u pathinfo=0
    
    sudo vi/etc/php/5.6/fpm/pool.d/www.conf
    listen=/run/php/php5.6-fpm.sock
    uwsgi
    sudo vi/etc/nginx/sites available/default
    
    对PHP使用嵌套位置,并让烧瓶保留在根中

    server {
        listen 80 default_server;
        listen [::]:80 default_server;
    
        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;
    
        root /var/www/html;
    
        # Add index.php to the list if you are using PHP
        index index.html index.htm index.php index.nginx-debian.html;
    
        server_name _;
    
        # Serve a static file (ex. favico) outside static dir.
        location = /favico.ico  {    
            root /var/www/html/favico.ico;    
        }
    
        # Proxying connections to application servers
        location / {
            include            uwsgi_params;
            uwsgi_pass         127.0.0.1:5000;
        }
    
        location /pcdp {
            location ~* \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
            }
        }
    
        location /phpmyadmin {
            location ~* \.php$ {
                try_files $uri =404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
            }
        }
    
        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #
        #location ~ \.php$ {
        #   include snippets/fastcgi-php.conf;
        #
        #   # With php7.0-cgi alone:
        #   fastcgi_pass 127.0.0.1:9000;
        #   # With php7.0-fpm:
        #   fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        #}
    
        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #   deny all;
        #}
    }
    
    仔细阅读

    我们需要了解位置匹配 (无):如果不存在修饰符,则位置将被解释为前缀匹配。这意味着给定的位置将与请求URI的开头匹配,以确定匹配。 =:I