jakimowicz-longurl 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +4 -0
- data/bin/longurl +15 -0
- data/lib/longurl.rb +51 -0
- data/lib/longurl/constants.rb +6 -0
- data/lib/longurl/direct.rb +15 -0
- data/lib/longurl/exceptions.rb +13 -0
- data/lib/longurl/service.rb +66 -0
- data/test/service_test.rb +47 -0
- metadata +70 -0
data/VERSION.yml
ADDED
data/bin/longurl
ADDED
data/lib/longurl.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# Copyright (c) 2009 by Fabien Jakimowicz (fabien@jakimowicz.com)
|
2
|
+
#
|
3
|
+
# Please see the LICENSE file for licensing.
|
4
|
+
|
5
|
+
require 'longurl/constants'
|
6
|
+
require 'longurl/exceptions'
|
7
|
+
require 'longurl/service'
|
8
|
+
require 'longurl/direct'
|
9
|
+
|
10
|
+
module LongURL
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
# Expand given <tt>:url</tt> to a longest one.
|
15
|
+
# First, expand will try to expand url using longurl.org service.
|
16
|
+
# Then, it will try to direct follow redirections on the given url and returns final one.
|
17
|
+
# === Options
|
18
|
+
# * <tt>:try_unsupported</tt> : use longurl.org to resolve the address, even if it is not a supported service
|
19
|
+
# * <tt>:direct_resolution</tt> : fetch url and follow redirection to find the final destination
|
20
|
+
# === Types
|
21
|
+
# <tt>url</tt> is expected to be a String and returns a String with the url.
|
22
|
+
# === Examples
|
23
|
+
# # simple expands
|
24
|
+
# LongURL.expand("http://tinyurl.com/1c2") # => "http://www.google.com"
|
25
|
+
# LongURL.expand("http://tinyurl.com/blnhsg") # => "http://www.google.com/search?q=number+of+horns+on+a+unicorn&ie=UTF-8"
|
26
|
+
# LongURL.expand("http://is.gd/iUKg") # => "http://fabien.jakimowicz.com"
|
27
|
+
#
|
28
|
+
# # not expandable urls, without any http call
|
29
|
+
# LongURL.expand("http://www.linuxfr.org") # => "http://www.linuxfr.org"
|
30
|
+
#
|
31
|
+
# # not expandable urls, calling longurl.org only
|
32
|
+
# LongURL.expand("http://www.linuxfr.org", :try_unsupported => true) # => "http://www.linuxfr.org/pub"
|
33
|
+
#
|
34
|
+
# # not expandable urls, direct resolution only
|
35
|
+
# LongURL.expand("http://www.linuxfr.org", :direct_resolution => true) # => "http://www.linuxfr.org/pub"
|
36
|
+
#
|
37
|
+
# # not expandable urls, longurl.org and direct resolution
|
38
|
+
# LongURL.expand("http://www.linuxfr.org",
|
39
|
+
# :try_unsupported => true, :direct_resolution => true) # => "http://www.linuxfr.org/pub"
|
40
|
+
# === Exceptions
|
41
|
+
# * LongURL::InvalidURL : will occurs if given url is nil, empty or invalid
|
42
|
+
# * LongURL::UnknownError : an unknown error occurs
|
43
|
+
def expand(url, options = {})
|
44
|
+
@@service ||= Service.new
|
45
|
+
options[:try_unsupported] ? @@service.query(url) : @@service.query_supported_service_only(url)
|
46
|
+
rescue UnsupportedService
|
47
|
+
options[:direct_resolution] ? Direct.follow_redirections(url) : url
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require "net/http"
|
3
|
+
|
4
|
+
module LongURL
|
5
|
+
module Direct
|
6
|
+
def self.follow_redirections(orig)
|
7
|
+
uri = URI.parse(orig)
|
8
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
9
|
+
answer = http.get(uri.path.empty? ? '/' : uri.path)
|
10
|
+
dest = answer['Location']
|
11
|
+
(dest && dest[0, 7] == 'http://' && follow_redirections(dest)) || orig
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module LongURL
|
2
|
+
# Raised by LongURL::Service class if longurl.org service returns unsupported service error.
|
3
|
+
class UnsupportedService < Exception
|
4
|
+
end
|
5
|
+
|
6
|
+
# Raised by LongURL::Service class if longurl.org service returns a not supported answer.
|
7
|
+
class UnknownError < Exception
|
8
|
+
end
|
9
|
+
|
10
|
+
# Raised by LongURL::Service if supplied url is invalid (nil, empty, ...)
|
11
|
+
class InvalidURL < Exception
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "cgi"
|
3
|
+
require "uri"
|
4
|
+
require "rubygems"
|
5
|
+
require "json"
|
6
|
+
require "longurl/constants"
|
7
|
+
require "longurl/exceptions"
|
8
|
+
|
9
|
+
module LongURL
|
10
|
+
|
11
|
+
class Service
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@@supported_services = fetch_supported_services
|
15
|
+
end
|
16
|
+
|
17
|
+
def query_supported_service_only(url)
|
18
|
+
check url
|
19
|
+
raise LongURL::UnsupportedService unless service_supported?(url)
|
20
|
+
query url
|
21
|
+
end
|
22
|
+
|
23
|
+
def query(url)
|
24
|
+
escaped_url = check_and_escape(url)
|
25
|
+
Net::HTTP.start(EndPoint.host, EndPoint.port) do |http|
|
26
|
+
handle_response http.get("#{EndPoint.path}?format=json&url=#{escaped_url}")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def service_supported?(url)
|
31
|
+
@@supported_services.include? URI.parse(url).host.downcase
|
32
|
+
end
|
33
|
+
|
34
|
+
def check(url)
|
35
|
+
raise LongURL::InvalidURL if url.nil? or url.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def check_and_escape(url)
|
41
|
+
check url
|
42
|
+
CGI.escape url
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch_supported_services
|
46
|
+
Net::HTTP.start(ServiceEndPoint.host, ServiceEndPoint.port) do |http|
|
47
|
+
response = http.get("#{ServiceEndPoint.path}?format=json")
|
48
|
+
parsed = JSON.parse(response.body)
|
49
|
+
parsed.values.flatten
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def handle_response(response)
|
54
|
+
parsed = JSON.parse(response.body)
|
55
|
+
if parsed['long_url']
|
56
|
+
parsed['long_url']
|
57
|
+
elsif parsed['message'] # Error
|
58
|
+
raise LongURL::UnsupportedService if parsed['messages']['message'] == 'Unsupported service.'
|
59
|
+
else
|
60
|
+
raise LongURL::UnknownError
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# tc_service.rb
|
2
|
+
#
|
3
|
+
# Created by Vincent Foley on 2005-06-01
|
4
|
+
|
5
|
+
$test_lib_dir = File.join(File.dirname(__FILE__), "..", "lib")
|
6
|
+
$:.unshift($test_lib_dir)
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
require "longurl/exceptions"
|
10
|
+
require "longurl/service"
|
11
|
+
|
12
|
+
class TestService < Test::Unit::TestCase
|
13
|
+
|
14
|
+
ShortToLong = {:tiny_url => {
|
15
|
+
"http://tinyurl.com/cnuw9a" => "http://fabien.jakimowicz.com",
|
16
|
+
"http://tinyurl.com/blnhsg" => "http://www.google.com/search?q=number+of+horns+on+a+unicorn&ie=UTF-8"
|
17
|
+
},
|
18
|
+
:is_gd => {
|
19
|
+
"http://is.gd/iUKg" => "http://fabien.jakimowicz.com",
|
20
|
+
"http://is.gd/iYCo" => "http://www.google.com/search?q=number+of+horns+on+a+unicorn&ie=UTF-8"
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
def setup
|
25
|
+
@service = LongURL::Service.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_query_should_raise_invalid_url_if_url_is_nil
|
29
|
+
assert_raise(LongURL::InvalidURL) { @service.query(nil) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_query_should_raise_invalid_url_if_url_is_empty
|
33
|
+
assert_raise(LongURL::InvalidURL) { @service.query('') }
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_query_should_returns_given_url_if_not_shorten_url
|
37
|
+
assert_equal "http://www.google.com", @service.query("http://www.google.com")
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_query_should_returns_expanded_url_for_tiny_url
|
41
|
+
ShortToLong[:tiny_url].each {|short, long| assert_equal long, @service.query(short)}
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_query_should_returns_expanded_url_for_is_gd
|
45
|
+
ShortToLong[:is_gd].each {|short, long| assert_equal long, @service.query(short)}
|
46
|
+
end
|
47
|
+
end
|
metadata
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jakimowicz-longurl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Fabien Jakimowicz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-02-10 00:00:00 -08:00
|
13
|
+
default_executable: longurl
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
description: LongURL expands short urls (tinyurl, is.gd, ...) to original ones, using on LongURL.org, internal resolution or direct resolution
|
25
|
+
email: fabien@jakimowicz.com
|
26
|
+
executables:
|
27
|
+
- longurl
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- VERSION.yml
|
34
|
+
- bin/longurl
|
35
|
+
- lib/longurl
|
36
|
+
- lib/longurl/constants.rb
|
37
|
+
- lib/longurl/direct.rb
|
38
|
+
- lib/longurl/exceptions.rb
|
39
|
+
- lib/longurl/service.rb
|
40
|
+
- lib/longurl.rb
|
41
|
+
- test/service_test.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: http://longurl.rubyforge.org
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options:
|
46
|
+
- --inline-source
|
47
|
+
- --charset=UTF-8
|
48
|
+
require_paths:
|
49
|
+
- lib
|
50
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: "0"
|
61
|
+
version:
|
62
|
+
requirements: []
|
63
|
+
|
64
|
+
rubyforge_project: longurl
|
65
|
+
rubygems_version: 1.2.0
|
66
|
+
signing_key:
|
67
|
+
specification_version: 2
|
68
|
+
summary: LongURL expands shorten urls (tinyurl, is.gd, ...)
|
69
|
+
test_files: []
|
70
|
+
|