jakimowicz-longurl 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|