เพิ่มคำนำหน้าไปยังเส้นทางขวดทั้งหมด


106

ฉันมีคำนำหน้าว่าฉันต้องการเพิ่มในทุกเส้นทาง ตอนนี้ฉันเพิ่มค่าคงที่ให้กับเส้นทางทุกคำจำกัดความ มีวิธีดำเนินการโดยอัตโนมัติหรือไม่?

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"

คำตอบ:


79

คำตอบขึ้นอยู่กับว่าคุณให้บริการแอปพลิเคชันนี้อย่างไร

ติดตั้งย่อยภายในคอนเทนเนอร์ WSGI อื่น

สมมติว่าคุณกำลังจะเรียกใช้แอปพลิเคชันนี้ภายในคอนเทนเนอร์ WSGI (mod_wsgi, uwsgi, gunicorn ฯลฯ ) คุณต้องติดตั้งจริงที่คำนำหน้าแอปพลิเคชันเป็นส่วนย่อยของคอนเทนเนอร์ WSGI นั้น (อะไรก็ตามที่พูดถึง WSGI จะทำ) และตั้งค่าการกำหนดAPPLICATION_ROOTค่าของคุณเป็นคำนำหน้า

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

การตั้งค่าAPPLICATION_ROOTคอนฟิกเพียง จำกัด เซสชันคุกกี้ของ Flask ไว้ที่คำนำหน้า URL นั้น ทุกสิ่งทุกอย่างจะถูกจัดการโดยอัตโนมัติสำหรับคุณโดยความสามารถในการจัดการ WSGI ที่ยอดเยี่ยมของ Flask และ Werkzeug

ตัวอย่างการติดตั้งแอปย่อยอย่างถูกต้อง

หากคุณไม่แน่ใจว่าย่อหน้าแรกหมายถึงอะไรลองดูตัวอย่างแอปพลิเคชั่นนี้โดยติดตั้ง Flask ไว้ด้านใน:

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)

คำขอมอบฉันทะไปยังแอป

ในทางกลับกันหากคุณกำลังเรียกใช้แอปพลิเคชัน Flask ของคุณที่รูทของคอนเทนเนอร์ WSGI และคำขอพร็อกซีไปยังมัน (ตัวอย่างเช่นหากเป็น FastCGI หรือถ้า nginx กำลังproxy_passร้องขอสำหรับจุดสิ้นสุดย่อย ไปยังเซิร์ฟเวอร์uwsgi/ สแตนด์อะโลนgeventของคุณจากนั้นคุณสามารถ:

  • ใช้พิมพ์เขียวเป็นมิเกลชี้ให้เห็นในคำตอบของเขา
  • หรือใช้DispatcherMiddlewarefrom werkzeug(หรือคำตอบPrefixMiddlewareจากsu27 ) เพื่อติดตั้งแอปพลิเคชันของคุณย่อยในเซิร์ฟเวอร์ WSGI แบบสแตนด์อะโลนที่คุณใช้ (ดูตัวอย่างการติดตั้งแอปย่อยอย่างถูกต้องด้านบนสำหรับโค้ดที่จะใช้)

@jknupp - มองหาที่flask.Flask#create_url_adapterและwerkzeug.routing.Map#bind_to_environดูเหมือนว่ามันควรจะทำงาน - วิธีที่คุณกำลังใช้รหัส? (แอปจำเป็นต้องติดตั้งบนพา ธ ย่อยในสภาพแวดล้อม WSGI url_forเพื่อส่งคืนค่าที่คาดหวัง)
Sean Vieira

ฉันวิ่งตามที่คุณเขียน แต่เพิ่ม app = Flask ( ชื่อ ) และ app.run (debug = True)
jeffknupp

4
@jknupp - นั่นคือปัญหา - คุณจะต้องติดตั้งแอปพลิเคชันเป็นส่วนย่อยของแอปพลิเคชันขนาดใหญ่ (ทุกอย่างที่พูดถึง WSGI จะทำ) ฉันได้รวบรวมส่วนสำคัญตัวอย่างและอัปเดตคำตอบเพื่อให้ชัดเจนขึ้นว่าฉันสมมติว่าสภาพแวดล้อม WSGI ที่ติดตั้งย่อยไม่ใช่สภาพแวดล้อม WSGI แบบสแตนด์อะโลนที่อยู่เบื้องหลังพร็อกซีซึ่งเป็นการส่งต่อคำขอพา ธ ย่อยเท่านั้น
Sean Vieira

3
วิธีนี้ใช้ได้ผลโดยใช้DispatcherMiddlewareวิธีนี้เมื่อใช้ขวดด้วยตัวเอง ดูเหมือนจะไม่สามารถทำงานได้เมื่อวิ่งตามหลัง Gunicorn
Justin

1
วิธีการติดตั้งไปยังเส้นทางย่อยใน uwsgi -s /tmp/yourapplication.sock --manage-script-name --mount /yourapplication=myapp:appuwsgi รายละเอียดอ้างถึง (เอกสาร uwsgi) [ flask.pocoo.org/docs/1.0/deploying/uwsgi/]
todaynowork

102

คุณสามารถกำหนดเส้นทางของคุณในพิมพ์เขียว:

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

2
สวัสดีมิเกล; คุณทราบความแตกต่างระหว่างการลงทะเบียน url_prefix สำหรับพิมพ์เขียวตามที่คุณทำด้านล่างกับapp.register_blueprintและระหว่างการลงทะเบียนเมื่อคุณสร้างอินสแตนซ์วัตถุพิมพ์เขียวด้านบนโดยการส่งผ่านurl_prefix='/abc/123? ขอขอบคุณ!
aralar

4
ความแตกต่างคือการมีคำนำหน้า URL ในการregister_blueprintโทรทำให้แอปพลิเคชันมีอิสระในการ "ต่อเชื่อม" พิมพ์เขียวได้ทุกที่ที่ต้องการหรือแม้กระทั่งติดตั้งพิมพ์เขียวเดียวกันหลาย ๆ ครั้งบน URL ที่ต่างกัน หากคุณใส่คำนำหน้าในพิมพ์เขียวคุณจะทำให้แอปพลิเคชันง่ายขึ้น แต่คุณมีความยืดหยุ่นน้อยกว่า
มิเกล

ขอขอบคุณ!! ที่เป็นประโยชน์มาก ฉันสับสนกับความซ้ำซ้อนที่เห็นได้ชัด แต่ฉันเห็นการแลกเปลี่ยนระหว่างสองตัวเลือก
aralar

และที่จริงฉันไม่เคยลองสิ่งนี้ แต่เป็นไปได้ว่าคุณสามารถรวมคำนำหน้า URL ทั้งในพิมพ์เขียวและแอปโดยใช้คำนำหน้าของแอปตามด้วยคำนำหน้าแบบพิมพ์เขียว
มิเกล

5
โปรดทราบว่าจำเป็นต้องลงทะเบียนพิมพ์เขียวหลังจากพิมพ์เขียวกำหนดเส้นทางฟังก์ชันตกแต่ง
Quint

55

คุณควรทราบว่าไม่ได้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ไม่ได้สำหรับงานนี้แม้ว่ามันจะดูเหมือนว่าจะเป็น มันสับสนจริงๆ


4
ขอขอบคุณที่เพิ่มคำตอบนี้ ลองใช้วิธีแก้ปัญหาอื่น ๆ ที่โพสต์ไว้ที่นี่ แต่นี่เป็นวิธีเดียวที่ใช้ได้ผลสำหรับฉัน A +++ ฉันใช้งานบน IIS โดยใช้ wfastcgi.py
sytech

"งานAPPLICATION_ROOTนี้ไม่เหมาะ" - นี่คือจุดที่ฉันคิดผิด ฉันหวังว่าBlueprint's url_prefixพารามิเตอร์และAPPLICATION_ROOTนำมารวมกันโดยค่าเริ่มต้นเพื่อที่ฉันจะมีAPPLICATION_ROOTURL ของขอบเขตสำหรับแอปทั้งหมดและurl_prefixURL ของขอบเขตภายในAPPLICATION_ROOTเพียงสำหรับพิมพ์เขียวของแต่ละบุคคล เฮ้อ
มนต์พิศ

ดูกระทู้นี้APPLICATION_ROOTสำหรับตัวอย่างของสิ่งที่ผมพยายามจะทำโดยใช้
พระภิกษุ

2
หากคุณใช้ gunicorn แสดงว่า SCRIPT_NAME ได้รับการสนับสนุนแล้ว ตั้งเป็นตัวแปรสภาพแวดล้อมหรือส่งผ่านเป็นส่วนหัว http: docs.gunicorn.org/en/stable/faq.html
เบลอร์แคท

1
รหัสตามที่ระบุไม่ได้ผลสำหรับฉัน หลังจากการวิจัยบางอย่างฉันได้พบกับสิ่งนี้ใน__call__วิธีอื่น: response = Response('That url is not correct for this application', status=404) return response(environ, start_response)โดยใช้from werkzeug.wrappers import BaseResponse as Response
Louis Becker

10

นี่เป็นคำตอบของ 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

เนื้อหานี้ค่อนข้าง hackish และอาศัยอยู่กับความจริงที่ว่าฟังก์ชั่นเส้นทางขวดต้องrouteเป็นอาร์กิวเมนต์ตำแหน่งแรก

คุณสามารถใช้มันได้ดังนี้:

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

หมายเหตุ: ไม่มีค่าอะไรเลยที่จะใช้ตัวแปรในคำนำหน้า (ตัวอย่างเช่นโดยการตั้งค่าเป็น/<prefix>) จากนั้นประมวลผลคำนำหน้านี้ในฟังก์ชันที่คุณตกแต่งด้วย@app.route(...)ไฟล์. หากคุณทำเช่นนั้นคุณต้องประกาศprefixพารามิเตอร์ในฟังก์ชันตกแต่งของคุณอย่างชัดเจน นอกจากนี้คุณอาจต้องการตรวจสอบคำนำหน้าที่ส่งมาเทียบกับกฎบางข้อและส่งคืน 404 หากการตรวจสอบล้มเหลว เพื่อหลีกเลี่ยงการนำ 404 ที่กำหนดเองมาใช้ใหม่โปรดตรวจสอบfrom werkzeug.exceptions import NotFoundแล้วraise NotFound()หากล้มเหลว


Blueprintมันง่ายและมีประสิทธิภาพมากขึ้นกว่าการใช้ ขอบคุณสำหรับการแบ่งปัน!
หนุ่ม HK

5

ดังนั้นฉันเชื่อว่าคำตอบที่ถูกต้องสำหรับสิ่งนี้คือคำนำหน้าควรได้รับการกำหนดค่าในแอปพลิเคชันเซิร์ฟเวอร์จริงที่คุณใช้เมื่อการพัฒนาเสร็จสมบูรณ์ 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)

ตอนนี้เมื่อรันโค้ดด้านบนเป็นแอพ Flask แบบสแตนด์อโลน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/

"ดังนั้นฉันเชื่อว่าคำตอบที่ถูกต้องคือคำนำหน้าควรได้รับการกำหนดค่าในแอปพลิเคชันเซิร์ฟเวอร์จริงที่คุณใช้เมื่อการพัฒนาเสร็จสมบูรณ์ Apache, nginx ฯลฯ " ปัญหาอยู่ในการเปลี่ยนเส้นทาง หากคุณมีคำนำหน้าและไม่ได้ตั้งค่าไว้ใน Flask เมื่อเปลี่ยนเส้นทางแทนที่จะไปที่ / yourprefix / path / to / url มันก็ไปที่ / path / to / url มีวิธีตั้งค่าใน nginx หรือ Apache คำนำหน้าต้องเป็นอย่างไร
Jordan Reiter

วิธีที่ฉันจะทำก็แค่ใช้เครื่องมือจัดการคอนฟิกูเรชันเช่นหุ่นเชิดหรือเชฟแล้วตั้งค่าคำนำหน้าจากนั้นให้เครื่องมือเผยแพร่การเปลี่ยนแปลงไปยังไฟล์คอนฟิกที่ต้องไป ฉันจะไม่แสร้งทำเป็นว่าฉันรู้ว่าฉันกำลังพูดถึง apache หรือ nginx อะไร เนื่องจากคำถาม / คำตอบนี้เป็นคำถามเฉพาะสำหรับ python ฉันขอแนะนำให้คุณโพสต์สถานการณ์ของคุณเป็นคำถามแยกต่างหาก หากคุณทำเช่นนี้อย่าลังเลที่จะเชื่อมโยงไปยังคำถามที่นี่!
พระภิกษุ

2

อีกวิธีหนึ่งที่แตกต่างอย่างสิ้นเชิงคือการใช้จุดเชื่อมต่อใน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คุณคุณต้องเปลี่ยนทั้ง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

และการกำหนดค่า nginx (อีกครั้งเพื่อความสมบูรณ์):

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')เนื่องจากจะปรับโดยอัตโนมัติ ด้วยวิธีนี้ลิงก์ของคุณจะทำงานได้โดยไม่มีปัญหาคำนำหน้า


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

1
โปรดพิจารณาเพิ่มคำอธิบาย
jpp

1
คำอธิบายที่ดีสองข้อที่ฉันพบอยู่ในexploreflaskและเอกสารอย่างเป็นทางการ
yuriploc

1

ฉันต้องการสิ่งที่เรียกว่า "บริบทรูท" ฉันทำในไฟล์ conf ภายใต้ /etc/httpd/conf.d/ โดยใช้ WSGIScriptAlias:

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


1

วิธีแก้ปัญหาของฉันที่แอป flask และ PHP อยู่ร่วมกัน nginx และ PHP5.6

KEEP Flask ในรูทและ 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

ใช้ NESTED LOCATIONS สำหรับ PHP และปล่อยให้ FLASK อยู่ในรูท

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/understand-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)

1

สำหรับผู้ที่ยังคงดิ้นรนกับสิ่งนี้ตัวอย่างแรกใช้งานได้ แต่ตัวอย่างเต็มอยู่ที่นี่หากคุณมีแอป 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,
    )
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.