关于python:尾部斜杠在Flask路径规则中触发404

Trailing slash triggers 404 in Flask path rule

我想将/users下的任何路径重定向到静态应用程序。下面的视图应该捕获这些路径并提供适当的文件(它只打印本例的路径)。这适用于/users/users/604511/users/604511/action。为什么路径/users/会导致404错误?

1
2
3
4
@bp.route('/users')
@bp.route('/users/<path:path>')
def serve_client_app(path=None):
    return path

您的/users路由缺少一个尾随斜杠,Werkzeug将其解释为与尾随斜杠不匹配的显式规则。或者添加尾随斜杠,如果URL没有,Werkzeug将重定向,或者在路由上设置strict_slashes=False,Werkzeug将匹配有斜杠或无斜杠的规则。

1
2
3
4
5
6
7
8
9
@app.route('/users/')
@app.route('/users/<path:path>')
def users(path=None):
    return str(path)

c = app.test_client()
print(c.get('/users'))  # 302 MOVED PERMANENTLY (to /users/)
print(c.get('/users/'))  # 200 OK
print(c.get('/users/test'))  # 200 OK
1
2
3
4
5
6
7
8
9
@app.route('/users', strict_slashes=False)
@app.route('/users/<path:path>')
def users(path=None):
    return str(path)

c = app.test_client()
print(c.get('/users'))  # 200 OK
print(c.get('/users/'))  # 200 OK
print(c.get('/users/test'))  # 200 OK

您还可以为所有URL设置strict_slashes

1
app.url_map.strict_slashes = False

但是,在大多数情况下,应该避免禁用严格的斜杠。文件解释了原因:

This behavior allows relative URLs to continue working even if the trailing slash is omitted, consistent with how Apache and other servers work. Also, the URLs will stay unique, which helps search engines avoid indexing the same page twice.


在全球范围内禁用严格的斜杠;将url_map.strict_slashes = False设置为这样:

1
2
app = Flask(__name__)
app.url_map.strict_slashes = False

这样,您就不必为每个视图使用strict_slashes=False

然后您只需定义不带尾随斜杠的路由,如下所示:

1
2
bp = Blueprint('api', __name__, url_prefix='/api')
@bp.route('/my-route', methods=['POST'])

然后,/my-route/my-route/都工作相同。


这是因为Werkzeug与其他HTTP服务器的一致性。查看烧瓶的快速入门文档。相关段落:

Unique URLs / Redirection Behavior

Flask’s URL rules are based on Werkzeug’s routing module. The idea
behind that module is to ensure beautiful and unique URLs based on
precedents laid down by Apache and earlier HTTP servers.

Take these two rules:

1
2
3
4
5
6
7
@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

Though they look rather similar, they differ in their use of the
trailing slash in the URL definition. In the first case, the canonical
URL for the projects endpoint has a trailing slash. In that sense, it
is similar to a folder on a file system. Accessing it without a
trailing slash will cause Flask to redirect to the canonical URL with
the trailing slash.

In the second case, however, the URL is defined without a trailing
slash, rather like the pathname of a file on UNIX-like systems.
Accessing the URL with a trailing slash will produce a 404"Not Found"
error.

This behavior allows relative URLs to continue working even if the
trailing slash is omitted, consistent with how Apache and other
servers work. Also, the URLs will stay unique, which helps search
engines avoid indexing the same page twice.

所以只需在路由中添加/users/