【问题标题】:Make a redirect without rendering the redirect page在不呈现重定向页面的情况下进行重定向
【发布时间】:2012-07-30 18:52:57
【问题描述】:

在用户提交一些数据以创建一个新对象后,我希望后端像往常一样将他重定向到对象详细信息:

我正在做类似的事情:

if obj.is_valid():
    obj.save()
    flash('%s created' % obj, )
    return redirect(url_for('provider', provider_id=obj.id))

但是通过 curl 发出请求(我正在构建一个 API,用 curl 测试它)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>Redirecting...</title>
<h1>Redirecting...</h1>
<p>You should be redirected automatically to target URL: <a href="/provider/11">/provider/11</a>.  If not click the link.
user@box

这很不幸,因为我只想要/provider/:id 的响应而不是中间步骤。

解决这个问题的正确方法是什么?

【问题讨论】:

  • 如果您不希望服务器发送重定向页面,则根本不想使用重定向。而是直接调用呈现/provider/11 页面的方法。请注意,如果您这样做,浏览器 URL 将显示他们最初点击的任何地址(不是 /provider/11),刷新页面将再次点击它。
  • 不,我想要一个重定向,而不是直接调用该方法... Django 的重定向正确地完成了这件事...
  • @tutaca “正确地”对不同的人有不同的含义。您是指 HTTP 302 (en.wikipedia.org/wiki/HTTP_302) 吗?当您使用上面的代码时,这就是 Flask 应该已经设置的内容。您没有向我们提供响应页面随附的 HTTP 标头...
  • Man...事情正在做一个香草重定向(只需阅读代码),这是烧瓶默认的302(文档是这样说的)...正确的意思是当我没有生成html时不要要求它...

标签: python redirect flask


【解决方案1】:

实际上,Flask 在这里按照RFC 2616 section 10.3.2 的定义做了正确的事情

新的永久 URI 应该由 回复。除非请求方法是 HEAD, 响应应该包含一个带有超链接的简短超文本注释 新的 URI。

[强调我的]

引用RFC 2119,这一段可以解释为:

HTTP 服务器必须包含带有 30X 重定向的简短超文本注释除非他们有充分的理由避免这样做

使用浏览器或任何通用 HTTP 库的人都不会看到该页面 - 客户端将遵循 RFC 2616 相关部分中指定的 Location 标头中提供的重定向。

暂且不说,如果你正在构建一个 JSON API,并且除了状态代码和必要的标头之外什么都不提供,你可以通过使用 Flask.errorhandler 装饰器为适当的方法注册你自己的错误处理程序来做到这一点,或者Flask.register_error_handler:

@app.errorhandler(302)
def minimal_redirect():
    return u"", 302

【讨论】:

    【解决方案2】:

    使用-L 指示 curl 它应该遵循 HTTP 重定向,并且只显示最终响应:

    $ curl -s http://www.exyr.org|grep '<title>' 
    <title>301 Moved Permanently</title>
    $ curl -s -L http://www.exyr.org|grep '<title>'
      <title>Exyr.org</title>
    

    man curl:

       -L, --location
              (HTTP/HTTPS)  If  the server reports that the requested page has
              moved to a different location (indicated with a Location: header
              and  a  3XX  response code), this option will make curl redo the
              request on the new place. If used together with -i, --include or
              -I, --head, headers from all requested pages will be shown. When
              authentication is used, curl only sends its credentials  to  the
              initial  host.  If a redirect takes curl to a different host, it
              won't be able to intercept the user+password. See  also  --loca‐
              tion-trusted  on how to change this. You can limit the amount of
              redirects to follow by using the --max-redirs option.
    
              When curl follows a redirect and the request is not a plain  GET
              (for example POST or PUT), it will do the following request with
              a GET if the HTTP response was 301, 302, or 303. If the response
              code  was  any  other  3xx code, curl will re-send the following
              request using the same unmodified method.
    

    【讨论】:

      【解决方案3】:

      我有类似的查询,因为烧瓶在重定向到目标本身之前重定向到 重定向页面

      只是删除code 实际上解决了这个问题。您还可以为每个 code 指定自定义路由/处理程序。

      redirect(url_for('home'), code=302)
      

      到,

      redirect(url_for('home'))
      

      或者正如@Sean Vieira 指出的,使用这个装饰器来处理重定向

      @app.errorhandler(302)
      def custom_redirect():
          # Return template
      

      【讨论】:

        【解决方案4】:

        您可以简单地删除redirect 响应的HTTP 正文。

        res = redirect(url_for('provider', provider_id=obj.id))
        res.data = ""
        return res
        

        【讨论】:

        • 不,这只会返回一个空白响应...我想要最终的 url 响应(在本例中为'/provider/11'。)
        猜你喜欢
        • 2012-05-25
        • 1970-01-01
        • 1970-01-01
        • 2012-04-10
        • 1970-01-01
        • 1970-01-01
        • 2011-11-06
        • 2013-10-12
        • 1970-01-01
        相关资源
        最近更新 更多