petit 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +11 -5
- data/bin/petit +2 -2
- data/lib/petit/core_ext.rb +68 -0
- data/lib/petit/rack_helper.rb +32 -3
- data/lib/petit/router.rb +23 -6
- data/lib/petit.rb +40 -7
- data/petit.gemspec +2 -2
- data/test/test_rack_helper.rb +20 -4
- data/test/test_router.rb +1 -1
- metadata +39 -45
data/README.md
CHANGED
@@ -5,10 +5,10 @@ file
|
|
5
5
|
|
6
6
|
## Highlights
|
7
7
|
|
8
|
-
* Your own url-shortner in minutes
|
8
|
+
* Your own git friendly url-shortner in minutes
|
9
9
|
* Links are precached, extremly fast routing
|
10
|
-
* Rack-based
|
11
|
-
* No
|
10
|
+
* Rack-based. Deploy on heroku in minutes
|
11
|
+
* No database setup
|
12
12
|
|
13
13
|
|
14
14
|
## Getting Started
|
@@ -19,7 +19,8 @@ file
|
|
19
19
|
|
20
20
|
### Initialize in the app directory
|
21
21
|
|
22
|
-
This will create links.yml in the current directory
|
22
|
+
This will create links.yml and config.ru in the current directory. Won't
|
23
|
+
overwrite if you already have them.
|
23
24
|
|
24
25
|
petit init
|
25
26
|
|
@@ -37,9 +38,14 @@ place this in your rackup file
|
|
37
38
|
require 'petit'
|
38
39
|
run Petit::Router.builder
|
39
40
|
|
41
|
+
## Sample
|
42
|
+
|
43
|
+
I use Petit for [g3rg.me](http://gr3g.me). Checkout the [source](https://github.com/gosuri/gr3g.me).
|
44
|
+
|
45
|
+
|
40
46
|
## Copying
|
41
47
|
|
42
|
-
Copyright (c) 2011 [Greg Osuri](http://
|
48
|
+
Copyright (c) 2011 [Greg Osuri](http://gr3g.me/about)
|
43
49
|
|
44
50
|
This is Free Software distributed under the terms of the MIT license.
|
45
51
|
See the file COPYING for information of licensing and distribution.
|
data/bin/petit
CHANGED
@@ -14,7 +14,7 @@ class PetitCommand < Thor
|
|
14
14
|
|
15
15
|
desc "server", "starts the petit routing server"
|
16
16
|
def server # :nodoc:
|
17
|
-
Petit
|
17
|
+
Petit.server
|
18
18
|
end
|
19
19
|
|
20
20
|
no_tasks do
|
@@ -23,7 +23,7 @@ class PetitCommand < Thor
|
|
23
23
|
create_file "config.ru" do
|
24
24
|
<<-CONTENT
|
25
25
|
require 'petit'
|
26
|
-
run Petit
|
26
|
+
run Petit.application
|
27
27
|
CONTENT
|
28
28
|
end
|
29
29
|
end
|
data/lib/petit/core_ext.rb
CHANGED
@@ -1,5 +1,73 @@
|
|
1
1
|
class Hash
|
2
|
+
|
3
|
+
# Renames the key in a hash
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# h = ["a" => 100, "b" => 200]
|
7
|
+
# h.rename_key("a","c")
|
8
|
+
# h # => ["c" => 100, "b" => 200]
|
9
|
+
# h["c"] # => 100
|
10
|
+
#
|
2
11
|
def rename_key(old,new)
|
3
12
|
self[new] = self.delete(old)
|
4
13
|
end
|
5
14
|
end
|
15
|
+
|
16
|
+
# Borrowed from active_support/core_ext/module/attribute_accessors.rb
|
17
|
+
# Extends the module object with module and instance accessors for class attributes,
|
18
|
+
# just like the native attr* accessors for instance attributes.
|
19
|
+
#
|
20
|
+
# module AppConfiguration
|
21
|
+
# mattr_accessor :google_api_key
|
22
|
+
# self.google_api_key = "123456789"
|
23
|
+
#
|
24
|
+
# mattr_accessor :paypal_url
|
25
|
+
# self.paypal_url = "www.sandbox.paypal.com"
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# AppConfiguration.google_api_key = "overriding the api key!"
|
29
|
+
class Module
|
30
|
+
def mattr_reader(*syms)
|
31
|
+
syms.each do |sym|
|
32
|
+
next if sym.is_a?(Hash)
|
33
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
34
|
+
unless defined? @@#{sym}
|
35
|
+
@@#{sym} = nil
|
36
|
+
end
|
37
|
+
def self.#{sym}
|
38
|
+
@@#{sym}
|
39
|
+
end
|
40
|
+
|
41
|
+
def #{sym}
|
42
|
+
@@#{sym}
|
43
|
+
end
|
44
|
+
EOS
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def mattr_writer(*syms)
|
49
|
+
options = syms.last.is_a?(::Hash) ? pop : {}
|
50
|
+
syms.each do |sym|
|
51
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
52
|
+
unless defined? @@#{sym}
|
53
|
+
@@#{sym} = nil
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.#{sym}=(obj)
|
57
|
+
@@#{sym} = obj
|
58
|
+
end
|
59
|
+
|
60
|
+
#{"
|
61
|
+
def #{sym}=(obj)
|
62
|
+
@@#{sym} = obj
|
63
|
+
end
|
64
|
+
" unless options[:instance_writer] == false }
|
65
|
+
EOS
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def mattr_accessor(*syms)
|
70
|
+
mattr_reader(*syms)
|
71
|
+
mattr_writer(*syms)
|
72
|
+
end
|
73
|
+
end
|
data/lib/petit/rack_helper.rb
CHANGED
@@ -2,19 +2,48 @@ module Petit
|
|
2
2
|
module RackHelper
|
3
3
|
class << self
|
4
4
|
|
5
|
-
#
|
5
|
+
# Generates a three part cached response for
|
6
|
+
# redirects with the url provided
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# RackHelper.redirect_response("http://foo.com")
|
11
|
+
# # above will return:
|
12
|
+
# # [ 301,
|
13
|
+
# # {
|
14
|
+
# # "Content-Type" => "text/plain",
|
15
|
+
# # "Location" => "http://foo.com",
|
16
|
+
# # "Cache-Control" => "max-age=7200, public"
|
17
|
+
# # },
|
18
|
+
# # [""]
|
19
|
+
# # ]
|
20
|
+
#
|
21
|
+
# Returns an array
|
6
22
|
def redirect_response(url)
|
7
|
-
[301, redirect_headers(url), [""]]
|
23
|
+
[301, cached(redirect_headers(url)), [""]]
|
8
24
|
end
|
9
25
|
|
10
|
-
# Generates a CGI-like redirect header hash
|
26
|
+
# Generates a CGI-like redirect header hash
|
11
27
|
# for the given url
|
28
|
+
# +url+ redirect url
|
29
|
+
#
|
30
|
+
# Returns an array
|
12
31
|
def redirect_headers(url)
|
13
32
|
{
|
14
33
|
"Content-Type" => "text/plain",
|
15
34
|
"Location" => url
|
16
35
|
}
|
17
36
|
end
|
37
|
+
|
38
|
+
# Appends HTTP cache headers to the hash
|
39
|
+
#
|
40
|
+
# headers - Hash http headers
|
41
|
+
# max_age - Cache expire maximum age (default: 7200)
|
42
|
+
#
|
43
|
+
# Returns a Hash
|
44
|
+
def cached(headers={}, max_age = 7200)
|
45
|
+
headers.merge({'Cache-Control' => "max-age=#{max_age}, public"})
|
46
|
+
end
|
18
47
|
end
|
19
48
|
end
|
20
49
|
end
|
data/lib/petit/router.rb
CHANGED
@@ -5,20 +5,37 @@ module Petit
|
|
5
5
|
class << self
|
6
6
|
|
7
7
|
# Generates a Rack::Builder object for URLs mapped redirects
|
8
|
+
#
|
8
9
|
# +links+ a hash of links to redirect
|
9
|
-
|
10
|
-
|
10
|
+
#
|
11
|
+
# Usage:
|
12
|
+
#
|
13
|
+
# require "petit"
|
14
|
+
#
|
15
|
+
# links = {
|
16
|
+
# '/foo' => 'http://bar.com',
|
17
|
+
# '/piyo' => 'http//fuga.com'
|
18
|
+
# }
|
19
|
+
# Petit::Router.application(links)
|
20
|
+
#
|
21
|
+
# Returns Rack::Builder
|
22
|
+
def application(links = Petit.links)
|
23
|
+
Rack::Builder.new do
|
11
24
|
links.each do |source,dest|
|
12
25
|
map source do
|
13
26
|
run Proc.new {|env| RackHelper.redirect_response(dest)}
|
14
|
-
|
27
|
+
end
|
15
28
|
end
|
16
29
|
end
|
17
30
|
end
|
18
31
|
|
19
|
-
|
20
|
-
|
21
|
-
|
32
|
+
|
33
|
+
# Starts the petit routing, this should be used in development mode
|
34
|
+
# port - port the server needs to start on (default: 4200)
|
35
|
+
# server - the type of server (default: webrick)
|
36
|
+
# Returns nothing
|
37
|
+
def server(port = 4200, server ='webrick')
|
38
|
+
Rack::Server.new(:app => application, :Port => port, :server => server).start
|
22
39
|
end
|
23
40
|
|
24
41
|
end
|
data/lib/petit.rb
CHANGED
@@ -8,18 +8,38 @@ module Petit
|
|
8
8
|
|
9
9
|
class << self
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
# optional config param to set the link source
|
12
|
+
# default: "links.yml"
|
13
|
+
#
|
14
|
+
# Usage:
|
15
|
+
#
|
16
|
+
# Petit.link_source = "app/links.yml"
|
17
|
+
#
|
18
|
+
mattr_accessor :link_source
|
14
19
|
|
15
20
|
def link_source
|
16
21
|
@@link_source ||= "links.yml"
|
17
22
|
end
|
18
|
-
|
19
|
-
|
23
|
+
# Loads the YAML file with link and returns a hash with urls
|
24
|
+
#
|
25
|
+
# source - source of the links file
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
# # contents of links.yml
|
29
|
+
# # :root http://my_app_with_long_domain.com
|
30
|
+
# # :foo http://bar.com
|
31
|
+
#
|
32
|
+
# Petit.links("links.yml)
|
33
|
+
# # will return:
|
34
|
+
# # {
|
35
|
+
# # '/' => 'http://my_app_with_long_domain.com',
|
36
|
+
# # '/foo' => 'http://bar.com'
|
37
|
+
# # }
|
38
|
+
#
|
39
|
+
def links(source = self.link_source)
|
20
40
|
unless @links
|
21
41
|
@links = {}
|
22
|
-
links = YAML::load(File.open(
|
42
|
+
links = YAML::load(File.open(link_source))
|
23
43
|
links.each do |key,url|
|
24
44
|
@links["/#{key}"] = url
|
25
45
|
end
|
@@ -28,11 +48,24 @@ module Petit
|
|
28
48
|
@links
|
29
49
|
end
|
30
50
|
|
31
|
-
# Default way to setup
|
51
|
+
# Default way to setup Petit
|
52
|
+
# Petit.config do |config|
|
53
|
+
# config.link_source = "routes.yml"
|
54
|
+
# end
|
32
55
|
def config
|
33
56
|
yield self
|
34
57
|
end
|
35
58
|
|
59
|
+
# @see Petit::Router.application
|
60
|
+
def application
|
61
|
+
Router.application
|
62
|
+
end
|
63
|
+
|
64
|
+
# @see Petit::Router.server
|
65
|
+
def server
|
66
|
+
Router.server
|
67
|
+
end
|
68
|
+
|
36
69
|
end
|
37
70
|
end
|
38
71
|
|
data/petit.gemspec
CHANGED
@@ -3,10 +3,10 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "petit"
|
6
|
-
s.version = "0.0.
|
6
|
+
s.version = "0.0.3"
|
7
7
|
s.authors = ["Greg Osuri"]
|
8
8
|
s.email = ["gosuri@gmail.com"]
|
9
|
-
s.homepage = "http://
|
9
|
+
s.homepage = "http://gr3g.me/petit"
|
10
10
|
s.summary = %q{a simple, fast, rack-based url shortening server}
|
11
11
|
s.description = %q{a simple, fast, rack-based url shortening server}
|
12
12
|
|
data/test/test_rack_helper.rb
CHANGED
@@ -3,16 +3,32 @@ require 'helper'
|
|
3
3
|
class TestRackHelper < Test::Unit::TestCase
|
4
4
|
|
5
5
|
def setup
|
6
|
-
@url
|
6
|
+
@url = "http://foo.com"
|
7
|
+
@headers = {"Content-Type" => "text/plain",
|
8
|
+
"Location" => @url}
|
7
9
|
end
|
8
10
|
|
9
11
|
def test_redirect
|
10
12
|
response = Petit::RackHelper.redirect_response(@url)
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
assertion = [
|
14
|
+
301,
|
15
|
+
{
|
16
|
+
"Content-Type"=>"text/plain",
|
17
|
+
"Location"=>"http://foo.com",
|
18
|
+
"Cache-Control"=>"max-age=7200, public"
|
19
|
+
},
|
20
|
+
[""]
|
21
|
+
]
|
22
|
+
assert_equal response, assertion
|
14
23
|
end
|
15
24
|
|
25
|
+
def test_cached_headers
|
26
|
+
headers = Petit::RackHelper.cached(@headers)
|
27
|
+
assert_equal headers["Content-Type"], "text/plain"
|
28
|
+
assert_equal headers["Location"], @url
|
29
|
+
assert_equal headers["Cache-Control"], "max-age=7200, public"
|
30
|
+
end
|
31
|
+
|
16
32
|
def test_redirect_headers
|
17
33
|
headers = Petit::RackHelper.redirect_headers(@url)
|
18
34
|
assert_equal headers["Content-Type"], "text/plain"
|
data/test/test_router.rb
CHANGED
@@ -8,7 +8,7 @@ class TestRouter < Test::Unit::TestCase
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def test_builder
|
11
|
-
assertion = Petit::Router.
|
11
|
+
assertion = Petit::Router.application(@links)
|
12
12
|
response = Rack::MockRequest.new(assertion).get("/foo")
|
13
13
|
assert_equal response.status, 301
|
14
14
|
assert_equal response.headers["Location"], "http://bar.com"
|
metadata
CHANGED
@@ -1,49 +1,46 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: petit
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
4
5
|
prerelease:
|
5
|
-
version: 0.0.2
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Greg Osuri
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-09-05 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: rack
|
17
|
-
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &70203330342620 !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
21
|
-
- -
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
24
22
|
type: :runtime
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: thor
|
28
23
|
prerelease: false
|
29
|
-
|
24
|
+
version_requirements: *70203330342620
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thor
|
27
|
+
requirement: &70203330342180 !ruby/object:Gem::Requirement
|
30
28
|
none: false
|
31
|
-
requirements:
|
32
|
-
- -
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version:
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
35
33
|
type: :runtime
|
36
|
-
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70203330342180
|
37
36
|
description: a simple, fast, rack-based url shortening server
|
38
|
-
email:
|
37
|
+
email:
|
39
38
|
- gosuri@gmail.com
|
40
|
-
executables:
|
39
|
+
executables:
|
41
40
|
- petit
|
42
41
|
extensions: []
|
43
|
-
|
44
42
|
extra_rdoc_files: []
|
45
|
-
|
46
|
-
files:
|
43
|
+
files:
|
47
44
|
- .gitignore
|
48
45
|
- COPYING
|
49
46
|
- Gemfile
|
@@ -62,34 +59,31 @@ files:
|
|
62
59
|
- test/test_petit.rb
|
63
60
|
- test/test_rack_helper.rb
|
64
61
|
- test/test_router.rb
|
65
|
-
homepage: http://
|
62
|
+
homepage: http://gr3g.me/petit
|
66
63
|
licenses: []
|
67
|
-
|
68
64
|
post_install_message:
|
69
65
|
rdoc_options: []
|
70
|
-
|
71
|
-
require_paths:
|
66
|
+
require_paths:
|
72
67
|
- lib
|
73
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
69
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
version:
|
79
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
75
|
none: false
|
81
|
-
requirements:
|
82
|
-
- -
|
83
|
-
- !ruby/object:Gem::Version
|
84
|
-
version:
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
85
80
|
requirements: []
|
86
|
-
|
87
81
|
rubyforge_project: petit
|
88
|
-
rubygems_version: 1.8.
|
82
|
+
rubygems_version: 1.8.8
|
89
83
|
signing_key:
|
90
84
|
specification_version: 3
|
91
85
|
summary: a simple, fast, rack-based url shortening server
|
92
|
-
test_files:
|
86
|
+
test_files:
|
93
87
|
- test/helper.rb
|
94
88
|
- test/links.yml
|
95
89
|
- test/sample_app/config.ru
|