programing

모든 플라스크 경로에 접두사 추가

javajsp 2023. 8. 2. 08:46

모든 플라스크 경로에 접두사 추가

모든 경로에 추가할 접두사가 있습니다.지금은 모든 정의에서 경로에 상수를 추가합니다.이것을 자동으로 할 수 있는 방법이 있습니까?

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"

경로를 Blueprint에 넣을 수 있습니다.

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"

그런 다음 접두사를 사용하여 애플리케이션에 Blueprint를 등록합니다.

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

이 응용 프로그램을 어떻게 제공하느냐에 따라 답이 달라집니다.

다른 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의 세션 쿠키가 해당 URL 접두사로 제한됩니다.플라스크와 Werkzeug의 뛰어난 WSGI 처리 능력으로 다른 모든 것이 자동으로 처리됩니다.

앱을 적절하게 서브마운트하는 예

첫 번째 단락이 무엇을 의미하는지 잘 모를 경우, 플라스크가 내부에 장착된 다음 예제 응용 프로그램을 살펴 보십시오.

from flask import Flask, url_for
from werkzeug.serving import run_simple
from werkzeug.middleware.dispatcher 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로 설정된 경우).proxy_pass 실행형에 하위 합니다. -ining은 당신의 것입니다.uwsgi/gevent서버에서 다음 중 하나를 수행할 수 있습니다.

  • Miguel이 답변에서 지적했듯이 Blueprint를 사용합니다.
  • 또는 를 사용합니다.DispatcherMiddlewarewerkzeug (또는또▁()PrefixMiddlewaresu27의 응답에서)를 클릭하여 사용 중인 독립 실행형 WSGI 서버에 응용 프로그램을 서브마운트합니다.(사용할 코드는 의 앱을 적절하게 서브마운트하는 예를 참조하십시오.)

당신은 주의해야 합니다.APPLICATION_ROOT이 목적은 아닙니다.

미들웨어를 작성하여 다음과 같이 변경하기만 하면 됩니다.

  1. 수정하다, 수정하다, 수정하다, 수정하다, 수정하다, 수정하다PATH_INFO접두사 URL을 처리합니다.
  2. 수정하다, 수정하다, 수정하다, 수정하다, 수정하다, 수정하다SCRIPT_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)

방문하다http://localhost:9010/foo/bar,

결과를 입니다: 올른결얻수있다니습을를과바.The URL for this page is /foo/bar

그리고 필요한 경우 쿠키 도메인을 설정하는 것을 잊지 마십시오.

이 해결책은 Larivact의 요지에 의해 주어집니다.APPLICATION_ROOT그럴 것 같지만 이 일에는 적합하지 않습니다.진짜 헷갈리네요.

이것은 플라스크/werkzeug 대답보다는 파이썬 답변에 가깝지만, 간단하고 효과적입니다.

나처럼 .inifile응용 를 포함하기 에)할 수 . file) 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

논쟁의 여지가 있지만, 이것은 다소 진부하며 플라스크 경로 함수가 필요로 한다는 사실에 의존합니다.route제1의 입장론으로서

다음과 같이 사용할 수 있습니다.

app = Flask(__name__)
app.route = prefix_route(app.route, '/your_prefix')

를 들어 NB: 에서변사예수용할아가것없습다치니가무설은정있는로다으음를수접변수를두사예▁nb▁in▁setting▁(▁it(▁nb▁that▁prefix▁it▁variable설for다니없:▁the정▁example습▁a▁by▁worth)./<prefix>), )로@app.route(...), 만그게한다면, ▁the합다니▁have▁if▁declare▁to야▁you▁obviously선언해,▁you▁so를 선언해야 합니다.prefix지정된 함수에 있는 매개 변수입니다.또한 일부 규칙에 대해 제출된 접두사를 확인하고 확인이 실패할 경우 404를 반환할 수 있습니다.404 사용자 지정 재구현을 방지하려면from werkzeug.exceptions import NotFound그리고 나서.raise NotFound()수표가 불합격될 경우

따라서 이에 대한 올바른 대답은 개발이 완료될 때 사용하는 실제 서버 응용프로그램에서 접두사를 구성해야 한다는 것입니다.Apache, nginx 등.

그러나 디버그에서 Flask 앱을 실행하는 동안 개발 중에 이 기능이 작동하기를 원한다면 이 요점을 살펴보십시오.

플라스크의DispatcherMiddleware구조를 위하여!

후세를 위해 코드를 여기에 복사하겠습니다.

"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)

의 코드를 할 때, 이제위코독플립앱때실행할로으크스라드,http://localhost:5000/spam/됩니다.Hello, world!.

다른 답변에 대한 댓글에서, 저는 다음과 같은 것을 하고 싶다고 표현했습니다.

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/

을 적용하는 중DispatcherMiddleware가 고안한 예 도의내 적 예로인::

from flask import Flask, Blueprint
from flask.serving import run_simple
from flask.wsgi import DispatcherMiddleware

# 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')
application = DispatcherMiddleware(Flask('dummy_app'), {
    app.config['APPLICATION_ROOT']: app
})
run_simple('localhost', 5000, application, use_reloader=True)

# Now, this url works!
# http://host:8080/api/some_submodule/record/1/

완전히 다른 또 다른 방법은 마운트 지점을 사용하는 것입니다.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

이 당신의 파일을 파을는않경우지호하출일우▁if경▁your는않▁you지▁file▁don.main.py당신은 둘 다 바꿀 필요가 있습니다.mount 리고그고.module

당신의.main.py다음과 같이 보일 수 있습니다.

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

그리고 anginx 구성(완전성을 위해 다시 한 번):

server {
  listen 80;
  server_name example.com

  location /foo {
    include uwsgi_params;
    uwsgi_pass unix:///temp/uwsgi.sock;
  }
}

나우콜링라고 부르고 있습니다.example.com/foo/bar됩니다./foo/bar플라스크에서 반송된 대로url_for('bar')자동으로 적응하기 때문입니다.이렇게 하면 접두사 문제 없이 링크가 작동합니다.

from flask import Flask

app = Flask(__name__)

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

if __name__ == "__main__":
    app.run(debug='True', port=4444)


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

@bp.route('/')
def test():
    return "success"

저는 "context-root"이라고 불리는 비슷한 것이 필요했습니다.저는 WSGIScriptAlias를 사용하여 /etc/httpd/conf.d/의 conf 파일에서 이 작업을 수행했습니다.

myapp.conf:

<VirtualHost *:80>
    WSGIScriptAlias /myapp /home/<myid>/myapp/wsgi.py

    <Directory /home/<myid>/myapp>
        Order deny,allow
        Allow from all
    </Directory>

</VirtualHost>

이제 다음과 같이 앱에 액세스할 수 있습니다. http://localhost:5000/myapp

가이드 참조 - http://modwsgi.readthedocs.io/en/develop/user-guides/quick-configuration-guide.html

플라스크와 PHP 앱이 nginx와 PHP 5.6이 공존하는 나의 솔루션

루트에는 플라스크를, 하위 디렉터리에는 PHP를 유지합니다.

sudo vi /etc/php/5.6/fpm/php.ini

1줄 추가

cgi.fix_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;
    #}
}

https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms 을 주의 깊게 읽으십시오.

위치 일치를 이해해야 합니다(없음).한정자가 없는 경우 해당 위치는 접두사 일치로 해석됩니다.즉, 지정된 위치가 요청 URI의 시작 부분과 일치하는지 확인합니다.등호를 사용하면 요청 URI가 지정된 위치와 정확히 일치하는 경우 이 블록이 일치하는 것으로 간주됩니다.타일 수정자가 있는 경우 이 위치는 대소문자를 구분하는 정규식 일치로 해석됩니다.타일 및 별표 수정자가 사용되는 경우 위치 블록은 대소문자를 구분하지 않는 정규식 일치로 해석됩니다.캐럿과 틸트 수정자가 있고 이 블록이 가장 좋은 비정규 표현식 일치로 선택된 경우 정규 표현식 일치가 수행되지 않습니다.

nginx의 "위치" 설명에서 순서는 중요합니다.

지정된 요청과 일치하는 위치를 찾기 위해 nginx는 먼저 접두사 문자열을 사용하여 정의된 위치(접두사 위치)를 확인합니다.그 중에서 일치하는 접두사가 가장 긴 위치가 선택되어 기억됩니다.그런 다음 정규식을 구성 파일에 나타나는 순서대로 검사합니다.정규식 검색은 첫 번째 일치에서 종료되고 해당 구성이 사용됩니다.정규식과 일치하는 것이 없으면 이전에 기억한 접두사 위치의 구성이 사용됩니다.

의미:

First =. ("longest matching prefix" match)
Then implicit ones. ("longest matching prefix" match)
Then regex. (first match)

여전히 이 문제로 어려움을 겪고 있는 사람들에게 첫 번째 예는 효과가 있지만, 사용자가 통제할 수 없는 Flask 앱이 있다면 전체 예는 다음과 같습니다.

from os import getenv
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from werkzeug.serving import run_simple
from custom_app import app

application = DispatcherMiddleware(
    app, {getenv("REBROW_BASEURL", "/rebrow"): app}
)

if __name__ == "__main__":
    run_simple(
        "0.0.0.0",
        int(getenv("REBROW_PORT", "5001")),
        application,
        use_debugger=False,
        threaded=True,
    )

플라스크 청사진에서 우리는 다음을 사용할 수 있습니다.

app = Flask(__name__)

app.config['APPLICATION_ROOT'] = '/prefix-text'

플라스크 휴식을 원하는 사람은 누구나 -을 이용할 수 있습니다.

문서 링크

app = Flask(__name__)

api = Api(app, prefix='/pefix-text')

이제 모든 경로에 다음과 같은 접두사가 붙습니다./prefix-text꼭 사용하시기 바랍니다.url_for('link')단순히 사용했을 수 있는 장소에서./link.

저는 su27의 답이 맞는 것 같습니다.그리고 저는 gevent를 사용하고 있습니다. 여기 제 코드가 있고 잘 작동합니다.

from gevent import pywsgi

# your flask code ...
# app = Flask(__name__)

if __name__ == "__main__":
    class MyHandler(pywsgi.WSGIHandler):
        def get_environ(self):
            prefix = "/your_prefix"
            env = super().get_environ()
            if env['PATH_INFO'].startswith(prefix):
                env['PATH_INFO'] = env['PATH_INFO'][len(prefix):]
                env['SCRIPT_NAME'] = prefix
            return env
    
    server = pywsgi.WSGIServer(('', 8080), app, handler_class=MyHandler)
    server.serve_forever()

제가 위에서 본 모든 대답들 중에서, 그것들은 너무 단순하거나 너무 복잡합니다.

즉, 중첩된 Blueprint를 사용하여 이를 달성하고 싶습니다.

from .blueprints import blueprint1, blueprint2, blueprint3, etc


app = Flask(__name__)

url_prefix = "/abc/123"
parent = Blueprint('index', __name__, url_prefix=url_prefix)

index.register_blueprint(blueprint1)
index.register_blueprint(blueprint2)
index.register_blueprint(blueprint3)
app.register_blueprint(index)

이렇게 하면 기본적으로 자식 Blueprint를 상위 Blueprint에 연결하고 접두사를 정의할 수 있습니다.이 문서는 여기에 설명되어 있습니다.

예를 들어 다음과 같이 다시 작성할 수 있습니다.

blueprint1 = Blueprint('blueprint1', __name__)

@blueprint1.route("/")
def index_page():
  return "Index page"

@blueprint1.route("/about")
def about_page():
  return "About page"

만약 당신의 목적이 어떤 식으로든 접두사를 추가하는 것이라면,

https://stackoverflow.com/a/73883005/553095 https://github.com/mskimm/prefixed-superset 의 답을 살펴보세요.

Nginx를 역방향 프록시로 사용할 때 접두사를 처리하려는 경우. 워크스그제.ProxyFix미들웨어는 더 간단한 솔루션이 될 것입니다.

from werkzeug.middleware.proxy_fix import ProxyFix
from flask import Flask


app = Flask(__name__)
app.wsgi_app = ProxyFix(
    app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1
)

는 Werkzeug를 읽을 입니다.X-Forwarded-Prefix를 헤더및설로 합니다.SCRIPT_NAME따라서 반드시 설정해야 합니다.X-Forwarded-PrefixNginx 구성의 헤더:

server {
    listen 80;
    server_name _;

    location /api {
        proxy_pass http://127.0.0.1:5000/;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Prefix /api;
    }
}

자세한 내용은 https://stackoverflow.com/a/75123044/5511849 에서 확인하십시오.

는 사용중을 하고 있습니다.ApiFlask 서버와 ""를 통한 gunicorn(하드웨어 및 운영 환경).바닐라에 대해서는 그 해결책이 효과가 있을 거라고 생각합니다.Flask뿐만 아니라.

는 한 - package 한서구 원함을 - 키지패__init__.py 가파일다니입는져에 있는 경로 를 가져오는 views.py경로를 정의하기 전에 더 많은 파일이나 일부 부분에서 그리고 그 이후에 나머지 부분에서 스패핑되지 않도록 하기 위한 파일입니다.다음을 통한 솔루션Blueprint경로를 구체적으로 주석을 달게 합니다. 이해는 하지만 제 경우에는 좀 지나친 것 같습니다.

솔루션은 다음을 기반으로 합니다.DispatcherMiddleware한 모든 루트파일에 됩니다.__init__.py 환경 변수의 접두사를 사용하고 있지만, 문제가 되지 않습니다.

자동으로 생성된 OAS 문서도 접두사가 지정된 경로로 액세스할있습니다.

최소 예제는 다음과 같습니다.

from apiflask import APIFlask
from werkzeug.middleware.dispatcher import DispatcherMiddleware
import os

route_prefix = os.getenv('APP_ROUTE_PREFIX', '')

def create_app():
    app = APIFlask(
            __name__,
            title="OAS3 Application title",
            version="0.2",
            docs_path='/docs',
            spec_path='/openapi.json'
    )
    app.config['APPLICATION_ROOT'] = route_prefix

    return app

app = create_app()
app.wsgi_app = DispatcherMiddleware(app, {route_prefix: app.wsgi_app})

from app.views import *

언급URL : https://stackoverflow.com/questions/18967441/add-a-prefix-to-all-flask-routes