Python 尾随斜杠在 Flask 路径规则中触发 404

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33241050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 13:05:02  来源:igfitidea点击:

Trailing slash triggers 404 in Flask path rule

pythonflask

提问by Jesvin Jose

I want to redirect any path under /usersto a static app. The following view should capture these paths and serve the appropriate file (it just prints the path for this example). This works for /users, /users/604511, and /users/604511/action. Why does the path /users/cause a 404 error?

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

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

采纳答案by davidism

Your /usersroute is missing a trailing slash, which Werkzeug interprets as an explicit rule to not match a trailing slash. Either add the trailing slash, and Werkzeug will redirect if the url doesn't have it, or set strict_slashes=Falseon the route and Werkzeug will match the rule with or without the slash.

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

@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
@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


You can also set strict_slashesfor all URLs.

您还可strict_slashes以为所有 URL设置。

app.url_map.strict_slashes = False

However, you should avoid disabling strict slashes in most cases. The docs explain why:

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

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 继续工作,这与 Apache 和其他服务器的工作方式一致。此外,URL 将保持唯一,这有助于搜索引擎避免将同一页面索引两次。

回答by Dauros

It's because of Werkzeug's consistency with other HTTP servers. Have a look at Flask's Quickstart documentation. The relevant paragraph:

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

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:

@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.

唯一 URL/重定向行为

Flask 的 URL 规则基于 Werkzeug 的路由模块。该模块背后的想法是确保基于 Apache 和早期 HTTP 服务器制定的先例的美丽和独特的 URL。

拿这两条规则:

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

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

尽管它们看起来相当相似,但它们在 URL 定义中尾随斜杠的使用有所不同。在第一种情况下,项目端点的规范 URL 有一个尾部斜杠。从这个意义上说,它类似于文件系统上的文件夹。不使用斜杠访问它会导致 Flask 重定向到带有斜杠的规范 URL。

然而,在第二种情况下,URL 的定义没有尾部斜杠,更像是类 UNIX 系统上的文件路径名。访问带有斜杠的 URL 将产生 404“未找到”错误。

即使省略了尾部斜杠,此行为也允许相对 URL 继续工作,这与 Apache 和其他服务器的工作方式一致。此外,URL 将保持唯一,这有助于搜索引擎避免将同一页面索引两次。

So just add /users/as well to the routing.

因此,只需将其添加/users/到路由中即可。

回答by Nick Woodhams

To disable strict slashes GLOBALLY; set url_map.strict_slashes = Falselike so:

全局禁用严格斜线;url_map.strict_slashes = False像这样设置:

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

This way you do not have to use strict_slashes=Falsefor each view.

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

Then you just define the route without a trailing slash like so:

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

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

Then /my-routeand /my-route/both work identically.

然后/my-route/my-route/两者的工作方式相同。