首页 > 解决方案 > URI.escape 的简单替代方案

问题描述

在 URL 上使用URI.parse时,我遇到了一条错误消息:

URI::InvalidURIError: URI must be ascii only

我发现了一个建议使用的 StackOverflow 问题URI.escape,它有效。以该问题中的 URL 为例:

URI.parse('http://dxczjjuegupb.cloudfront.net/wp-content/uploads/2017/10/Оуэн-Мэтьюс.jpg')
=> URI::InvalidURIError: URI must be ascii only "http://dxczjjuegupb.cloudfront.net/wp-content/uploads/2017/10/\u041E\u0443\u044D\u043D-\u041C\u044D\u0442\u044C\u044E\u0441.jpg"

URI.encode('http://dxczjjuegupb.cloudfront.net/wp-content/uploads/2017/10/Оуэн-Мэтьюс.jpg')
=> "http://dxczjjuegupb.cloudfront.net/wp-content/uploads/2017/10/%D0%9E%D1%83%D1%8D%D0%BD-%D0%9C%D1%8D%D1%82%D1%8C%D1%8E%D1%81.jpg"

但是,URI.escape正如Rubocop警告的那样,它已经过时了:

URI.escape method is obsolete and should not be used. Instead, use CGI.escape, URI.encode_www_form or URI.encode_www_form_component depending on your specific use case.

但是,虽然URI.escape给了我们一个可用的结果,但替代方案不会:

CGI.escape('http://dxczjjuegupb.cloudfront.net/wp-content/uploads/2017/10/Оуэн-Мэтьюс.jpg')
=> "http%3A%2F%2Fdxczjjuegupb.cloudfront.net%2Fwp-content%2Fuploads%2F2017%2F10%2F%D0%9E%D1%83%D1%8D%D0%BD-%D0%9C%D1%8D%D1%82%D1%8C%D1%8E%D1%81.jpg"

这很麻烦,因为在我的情况下,我正在从通过Nokogiri获得的数据构建一个 URL :

my_url = page.at('.someclass').at('img').attr('src')

由于我只需要转义生成的 URL 的最后一部分,但CGI.escape类似地转换整个字符串(包括必要的字符,例如:and /),现在获得转义的结果变成了多行代码的考验,不得不拆分路径并使用多个变量来实现以前使用单个函数 ( URI.escape) 可以完成的任务。

有没有我没有看到的简单替代方案?它需要在没有外部宝石的情况下完成。

标签: rubyescapinguri

解决方案


我倾向于使用Addressable解析 URL,因为该标准URI存在缺陷:

require 'addressable'

Addressable::URI.parse('http://dxczjjuegupb.cloudfront.net/wp-content/uploads/2017/10/Оуэн-Мэтьюс.jpg')
#<Addressable::URI:0x3fc37ecc1c40 URI:http://dxczjjuegupb.cloudfront.net/wp-content/uploads/2017/10/Оуэн-Мэтьюс.jpg> 

Addressable::URI.parse('http://dxczjjuegupb.cloudfront.net/wp-content/uploads/2017/10/Оуэн-Мэтьюс.jpg').path
# "/wp-content/uploads/2017/10/Оуэн-Мэтьюс.jpg" 

它不是 Ruby 核心或标准库的一部分,但它应该是并且它总是以我Gemfile的 s.


推荐阅读