没有数据库的URL缩短器

时间:2011-01-27 15:40:34

标签: url-shortener

我想写一个不需要使用数据库的URL缩短器。相反,为了拥有尽可能少的移动部件,脚本将根据算法为我的URL创建一个唯一的哈希(如md5,除了md5太长)。我不确定我该怎么做。有什么建议吗?

如果重要,我宁愿用Ruby写这个。

4 个答案:

答案 0 :(得分:1)

您可以使用几种可用于将URL转换为模糊的字符串操作工具来执行此操作,但正如您在问题中所指出的,您执行此操作所获得的URL将比网址缩短器的典型值更长。

网址不能很好地压缩。

答案 1 :(得分:1)

最终,如果你是一个简短的链接,你只需要生成一个适当易读的唯一的代码(尝试省略类似的字母/数字,如零和'o',以防一些穷人bugger实际上必须输入它并将该代码与某种形式的商店中的原始URL相关联。

虽然我可以理解为什么你不想使用数据库,但在很多方面它都是完美的存储形式,特别是如果你看一个专用的键/值存储,例如Cassandra,{ {3}},Redis等(也就是说,如果您处于不熟悉的领域,简单的“传统”SQL数据库可能是第一步。)

答案 2 :(得分:0)

如果不在某种数据库中查找,您将无法从哈希代码中解析原始URL。

关于在没有数据库的情况下唯一可以做的就是压缩URL,然后在解析URL时将其解压缩。

严格来说,我猜你可以只是对网址进行哈希处理。但是,如果您无法将其解析回原始网址,那将会有什么价值呢?

答案 3 :(得分:0)

您需要的是一种压缩和解压缩String的方法。其中生成的压缩版本也是字符串。这几乎是不可能的,因为URL已经很短了。编码和无损压缩始终会增加最小的开销,对于大多数URL来说,这将导致字符串大于原始字符串。

但是对于很长的URL,它可能会起作用。

因此,最后,您几乎总是需要存储(数据库)中的查找表。

Base64是最合乎逻辑的解决方案。然而,就短字符串(通常是URL)而言,Base64编码返回的字符串比原始字符串更长。由于填充,主要是。因此,我们还将尝试使用zlib来压缩字符串。

require "uri"
require "base64"
require "zlib"

shortner_url = URI.parse("https://s.to")
long = "https://stackoverflow.com/questions/4818429/url-shortener-with-no-database"
url = URI.parse(long) 
stripped = url.host + url.path
stripped.length #=> 66

# Let's see that Base64 on its own does not shorten the url.
encoded = Base64.encode64(stripped)
encoded.length #=> 90

# So, using zlib. To compress.
compressed = Zlib::Deflate.deflate(stripped)
encoded = Base64.encode64(compressed)
encoded.length #=> 94 
# It became worse.

# Now, with a long url (they can be much longer even), in a oneliner; to simplify omit the stripping part:
long = "http://www.thelongestlistofthelongeststuffatthelongestdomainnameatlonglast.com/wearejustdoingthistobestupidnowsincethiscangoonforeverandeverandeverbutitstilllookskindaneatinthebrowsereventhoughitsabigwasteoftimeandenergyandhasnorealpointbutwehadtodoitanyways.html"
long.length #=> 263
Base64.encode64(Zlib::Deflate.deflate(long)).length #=> 228

# In order to turn this into a valid short URL, however, we need `urlsaf_encode64()`

shortner_url.path = "/" + Base64.urlsafe_encode64(Zlib::Deflate.deflate(long))
shorther_url.to_s #=> "https://s.to/eJxNjkEWwyAIRG-U7HsbElFpEPIE68vti6t2BcwbZn51v1_7PufcvCKrFDRnMtf8u81HzuA_IWkDEoGG4EtiMN9ObftE6Pgey0FSvK6gIx7GTUl0GsmJSz1Biqpk7fjBDpL-xjGcopKYWfWyiySBRBFJABw9UnB9xaWj1LDCQWUGAQYzBVLECPbyxFLBJDqA7-DxSJ5YIbkGnoM8Ex7bqjf-AiodbYM="
 shortner_url.to_s.length #=> 237 WE SAVED 26 characters!

有关剥离的注释:可以删除“ https://”。 Real实现需要在字符串中添加一段,以确定https或http:https的结果为'1'+ res,http的结果为'0'+ result。另一个“黑客”是使网址缩短服务将http用作http url,将https用作https url。

如果您始终拥有相同的域,则也可以忽略域部分。

如果您有很多斜杠或其他重复字符(例如破折号),则压缩效果更好。