【问题标题】:Trailing slash in Flask routeFlask 路径中的斜杠
【发布时间】:2016-11-01 17:30:15
【问题描述】:

以以下两条路线为例。

app = Flask(__name__)

@app.route("/somewhere")
def no_trailing_slash():
    #case one

@app.route("/someplace/")
def with_trailing_slash():
    #case two

根据the docs理解如下:

  • 在第一种情况下,对路由 "/somewhere/" 的请求将返回 404 响应。 "/somewhere" 有效。

  • 情况二,"/someplace/" 有效,"/someplace" 将重定向到"/someplace/"

我希望看到的行为是 case 2 行为的 'inverse'。例如"/someplace/" 将重定向到 "/someplace" 而不是相反。有没有办法定义采取这种行为的路线?

据我了解,strict_slashes=False 可以在路由上设置以在情况一中有效地获得与情况二相同的行为,但我想做的是让重定向行为始终重定向到 URL 没有尾部斜杠。

我想到的一个解决方案是使用 404 的错误处理程序,类似这样。 (不确定这是否可行)

@app.errorhandler(404)
def not_found(e):
    if request.path.endswith("/") and request.path[:-1] in all_endpoints:
        return redirect(request.path[:-1]), 302
    return render_template("404.html"), 404

但我想知道是否有更好的解决方案,例如某种插入式应用程序配置,类似于我可以全局应用的strict_slashes=False。也许是蓝图或 url 规则?

【问题讨论】:

  • 分别实现并让/somplace/重定向到/someplace?
  • 我注意到的是,当您的 Flask 配置中有 DEBUG=True 时,尾随空格不会被重定向,但是当 DEBUG=False 时,它会被重定向。
  • @Busturdust 可能会起作用,但管理起来会很痛苦。我的其他一些想法涉及使用error handler,如果存在无斜线端点,则返回重定向。也可以使用某种蓝图。但是我已经为其他东西使用了 404 错误处理程序(它可以被烘焙,但我宁愿不这样做)而且我不确定它是否可以通过蓝图来实现。理想的解决方案是像全局 url 规则这样的插件。
  • @kiran.koduru 这是一个有趣的观察。我将不得不看一下,尽管出于显而易见的原因,我认为我不会在生产中使用调试标志。我通常使用 Tornado 或 gEvent 部署 Flask。即使我设置了app.debug = True,它似乎也没有接受 gevent WSGI 环境。我确信有一种方法可以解决 that 问题,但这是另一个问题,正如所解释的那样,对于生产环境,可能不是 this 问题的适用解决方案。跨度>

标签: python flask


【解决方案1】:

您使用strict_slashes 进行正确跟踪,您可以在 Flask 应用程序本身上进行配置。这将为创建的每条路由设置 strict_slashes 标志为 False

app = Flask('my_app')
app.url_map.strict_slashes = False

然后您可以使用before_request 来检测尾随/ 以进行重定向。使用before_request 将允许您不需要将特殊逻辑单独应用于每个路由

@app.before_request
def clear_trailing():
    from flask import redirect, request

    rp = request.path 
    if rp != '/' and rp.endswith('/'):
        return redirect(rp[:-1])

【讨论】:

  • 当然,我已经搞定了这么多。但是,这将重定向到带有尾随斜杠 的 URL。对非尾随斜杠的请求将是 302 重定向。我希望尾部斜杠重定向到非尾部斜杠 URL。
  • 这看起来很有趣。这可能适用于解决方案。如果我采用这种方法,我可能会在重定向之前先检查 slashless 路由是否存在,以避免重定向到最终将是 404 的 URL。但是,是的,这看起来不错。我不确定注册一个函数以运行每条路线每次的感觉如何。我正在权衡使用 404 错误处理程序来检查无斜线路由是否存在,我认为只有在发生 404 时才会运行,并且与此相比可能会或可能不会对性能产生影响。
【解决方案2】:

如果您希望以相同的方式处理两条路线,我会这样做:

app = Flask(__name__)

@app.route("/someplace/")
@app.route("/someplace")
def slash_agnostic():
    #code for both routes

【讨论】:

  • 如果/someplace 是命名空间前缀呢?
  • @ZobayerHasan,我不明白这个问题。您是在描述这样的路径:/someplace/someplace
  • 不,我使用的是烧瓶 restplus。在 restplus 中,命名空间的使用就像蓝图一样。例如,我可以注册一个带有/someplace前缀的命名空间,然后在我的资源类中,我可以设置@api.route('/')来创建路径/someplace/
  • 我没有使用过restplus,所以我不确定类似的东西是否可以在那里工作。
  • 没关系,因为我后来在阅读了更多关于 REST api 路由设计的内容后发现,尾部的斜杠实际上代表了一些东西。 softwareengineering.stackexchange.com/a/187006/201023
【解决方案3】:

您还可以在路由定义中使用选项 strict_slashes=False:

app.Flask(__name__)
@app.route("/someplace", strict_slashes=False)
# Your code goes here

【讨论】:

    猜你喜欢
    • 2016-01-19
    • 2012-11-16
    • 2013-01-28
    • 2017-03-16
    • 2020-11-20
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多