【问题标题】:Sinatra/Rack `ERROR URI::InvalidURIError: bad URI(is not URI?)` on redirectSinatra/Rack `ERROR URI::InvalidURIError: bad URI(is not URI?)` 重定向
【发布时间】:2013-02-01 23:59:01
【问题描述】:

我刚刚开始了我的第一个 Sinatra 项目,这是一个简单的电视节目管理 Web 应用程序,并且想要拥有漂亮的 URL。因此,当用户在搜索框中键入并提交时,我不想拥有 /?search=foobar 样式的 URL,而是希望将它们重定向到 /search/foobar。这也使我能够将 get '/search/:name 路由与主要的 get '/' 路由分开。我已经使用before 过滤器实现了重定向,并正确转义了params[] 变量:

before do
    if params.has_key? 'search'
        redirect to("/search/#{URI.escape(params['search'])}")
    end
end

然后我继续

get '/search/:query' do
    result = search_api params[:query]
    if result == 'null'
        # no results
    else
        result = JSON.parse(result)
        if result.key? 'shows'
            # display search results
        else
            # redirect to one single show
            # (result.keys).first is the real name of the show provided
            # by the api. It may contain special characters
            #
            # (result.keys).first #=> "Breaking Bad"
            # result.keys #=> "Breaking Bad"
            # result.key? "Breaking Bad" #=> true
            redirect to('/show/#{URI.escape((result.keys).first)}')
        end
    end
end

不幸的是,重定向到/show 页面仅适用于名称中除了% 之外没有URI 特殊字符的情况。这也意味着没有空格。当我搜索带有空格或变音符号或任何东西的东西时,例如GET for /?search=Breaking%20Bad,我从 Sinatra/Rack 收到以下错误:

[2013-02-02 00:30:29] ERROR URI::InvalidURIError: bad URI(is not URI?): http://localhost:9393/show/Breaking Bad
    /Users/Ps0ke/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/uri/generic.rb:1202:in `rescue in merge'
    /Users/Ps0ke/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/uri/generic.rb:1199:in `merge'
    /Users/Ps0ke/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpresponse.rb:220:in `setup_header'
    /Users/Ps0ke/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpresponse.rb:150:in `send_response'
    /Users/Ps0ke/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpserver.rb:110:in `run'
    /Users/Ps0ke/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'

浏览器告诉我,它被重定向到/search/Breaking%20Bad,所以第一个重定向有效。此“错误”仅在搜索产生精确命中时发生,因此重定向的问题是在 get '/search/:query' 路由中搜索。我记得它工作过一次,但在我的 git 历史记录中找不到正确的提交。

我在跑步

% gem list sinatra
sinatra (1.3.4, 1.3.3)

% gem list rack
rack (1.4.4, 1.4.1)
rack-cache (1.2)
rack-flash3 (1.0.3)
rack-protection (1.3.2, 1.2.0)
rack-ssl (1.3.2)
rack-test (0.6.2, 0.6.1)

也许有人可以告诉我:

  1. 这是好的还是坏的做法/在 sinatra 中还有另一种美化 URL 的方法
  2. 如何解决这个问题,因为我想我已经小心翼翼地逃脱了一切

提前非常感谢你:)

【问题讨论】:

  • 澄清一下,调用result.keys 的结果是什么(例如)? “绝命毒师” ?请添加您正在使用的 Sinatra 和 Rack 版本。

标签: ruby escaping sinatra uri rack


【解决方案1】:

排队

redirect to('/show/#{URI.escape((result.keys).first)}')

您正在使用单引号。这意味着不执行字符串插值,因此文字字符串 /show/#{URI.escape((result.keys).first)} 被用作 url,这就是它失败的原因。

为了使插值工作,您需要使用这样的双引号:

redirect to("/show/#{URI.escape((result.keys).first)}")

这将导致 #{URI.escape((result.keys).first)} 被转义的电影名称替换,这应该是一个有效的 url。

请注意,在您的第一个重定向中,您确实使用了双引号,因此它可以按预期工作:

redirect to("/search/#{URI.escape(params['search'])}")

【讨论】:

  • 天哪,这太尴尬了!有时您为我们的调试而忽略了树木的木材。谢谢。
  • 一些文本编辑器(如 Sublime Text)会以不同的颜色突出显示插值部分(如果您使用了双引号),以便您可以看到它将被插值。
猜你喜欢
  • 2017-12-18
  • 2018-06-12
  • 2020-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-09
  • 2012-02-23
  • 2011-07-19
相关资源
最近更新 更多