webmachine 0.1.0
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/.gitignore +28 -0
- data/Gemfile +16 -0
- data/Guardfile +11 -0
- data/README.md +89 -0
- data/Rakefile +31 -0
- data/examples/webrick.rb +19 -0
- data/lib/webmachine/adapters/webrick.rb +74 -0
- data/lib/webmachine/adapters.rb +15 -0
- data/lib/webmachine/decision/conneg.rb +304 -0
- data/lib/webmachine/decision/flow.rb +502 -0
- data/lib/webmachine/decision/fsm.rb +79 -0
- data/lib/webmachine/decision/helpers.rb +80 -0
- data/lib/webmachine/decision.rb +12 -0
- data/lib/webmachine/dispatcher/route.rb +85 -0
- data/lib/webmachine/dispatcher.rb +40 -0
- data/lib/webmachine/errors.rb +37 -0
- data/lib/webmachine/headers.rb +16 -0
- data/lib/webmachine/locale/en.yml +28 -0
- data/lib/webmachine/request.rb +56 -0
- data/lib/webmachine/resource/callbacks.rb +362 -0
- data/lib/webmachine/resource/encodings.rb +36 -0
- data/lib/webmachine/resource.rb +48 -0
- data/lib/webmachine/response.rb +49 -0
- data/lib/webmachine/streaming.rb +27 -0
- data/lib/webmachine/translation.rb +11 -0
- data/lib/webmachine/version.rb +4 -0
- data/lib/webmachine.rb +19 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/tests.org +57 -0
- data/spec/webmachine/decision/conneg_spec.rb +152 -0
- data/spec/webmachine/decision/flow_spec.rb +1030 -0
- data/spec/webmachine/dispatcher/route_spec.rb +109 -0
- data/spec/webmachine/dispatcher_spec.rb +34 -0
- data/spec/webmachine/headers_spec.rb +19 -0
- data/spec/webmachine/request_spec.rb +24 -0
- data/webmachine.gemspec +44 -0
- metadata +137 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Webmachine::Dispatcher::Route do
|
4
|
+
let(:request){ Webmachine::Request.new("GET", URI.parse("http://localhost:8098/"), Webmachine::Headers.new, "") }
|
5
|
+
let(:resource){ Class.new(Webmachine::Resource) }
|
6
|
+
|
7
|
+
matcher :match_route do |*expected|
|
8
|
+
route = described_class.new(expected[0], resource, expected[1] || {})
|
9
|
+
match do |actual|
|
10
|
+
request.uri.path = actual if String === actual
|
11
|
+
route.match?(request)
|
12
|
+
end
|
13
|
+
|
14
|
+
failure_message_for_should do |_|
|
15
|
+
"expected route #{expected[0].inspect} to match path #{request.uri.path}"
|
16
|
+
end
|
17
|
+
failure_message_for_should_not do |_|
|
18
|
+
"expected route #{expected[0].inspect} not to match path #{request.uri.path}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "matching a request" do
|
23
|
+
context "on the root path" do
|
24
|
+
subject { "/" }
|
25
|
+
it { should match_route([]) }
|
26
|
+
it { should match_route ['*'] }
|
27
|
+
it { should_not match_route %w{foo} }
|
28
|
+
it { should_not match_route [:id] }
|
29
|
+
end
|
30
|
+
|
31
|
+
context "on a deep path" do
|
32
|
+
subject { "/foo/bar/baz" }
|
33
|
+
it { should match_route %w{foo bar baz} }
|
34
|
+
it { should match_route ['foo', :id, "baz"] }
|
35
|
+
it { should match_route %w{foo *} }
|
36
|
+
it { should match_route [:id, '*'] }
|
37
|
+
it { should_not match_route [] }
|
38
|
+
it { should_not match_route %w{bar *} }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "applying bindings" do
|
43
|
+
context "on the root path" do
|
44
|
+
subject { described_class.new([], resource) }
|
45
|
+
before { subject.apply(request) }
|
46
|
+
|
47
|
+
it "should assign the dispatched path to the empty string" do
|
48
|
+
request.disp_path.should == ""
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should assign empty bindings" do
|
52
|
+
request.path_info.should == {}
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should assign empty path tokens" do
|
56
|
+
request.path_tokens.should == []
|
57
|
+
end
|
58
|
+
|
59
|
+
context "with extra user-defined bindings" do
|
60
|
+
subject { described_class.new([], resource, "bar" => "baz") }
|
61
|
+
|
62
|
+
it "should assign the user-defined bindings" do
|
63
|
+
request.path_info.should == {"bar" => "baz"}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "with a splat" do
|
68
|
+
subject { described_class.new(['*'], resource) }
|
69
|
+
|
70
|
+
it "should assign empty path tokens" do
|
71
|
+
request.path_tokens.should == []
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "on a deep path" do
|
77
|
+
subject { described_class.new(%w{foo bar baz}, resource) }
|
78
|
+
before { request.uri.path = "/foo/bar/baz"; subject.apply(request) }
|
79
|
+
|
80
|
+
it "should assign the dispatched path as the path past the initial slash" do
|
81
|
+
request.disp_path.should == "foo/bar/baz"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should assign empty bindings" do
|
85
|
+
request.path_info.should == {}
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should assign empty path tokens" do
|
89
|
+
request.path_tokens.should == []
|
90
|
+
end
|
91
|
+
|
92
|
+
context "with path variables" do
|
93
|
+
subject { described_class.new(['foo', :id, 'baz'], resource) }
|
94
|
+
|
95
|
+
it "should assign the path variables in the bindings" do
|
96
|
+
request.path_info.should == {:id => "bar"}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "with a splat" do
|
101
|
+
subject { described_class.new(%w{foo *}, resource) }
|
102
|
+
|
103
|
+
it "should capture the path tokens matched by the splat" do
|
104
|
+
request.path_tokens.should == %w{ bar baz }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Webmachine::Dispatcher do
|
4
|
+
let(:dispatcher) { described_class }
|
5
|
+
let(:request) { Webmachine::Request.new("GET", URI.parse("http://localhost:8080/"), Webmachine::Headers["accept" => "*/*"], "") }
|
6
|
+
let(:response) { Webmachine::Response.new }
|
7
|
+
let(:resource) do
|
8
|
+
Class.new(Webmachine::Resource) do
|
9
|
+
def to_html; "hello world!"; end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
let(:resource2) do
|
13
|
+
Class.new(Webmachine::Resource) do
|
14
|
+
def to_html; "goodbye, cruel world"; end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
let(:fsm){ mock }
|
18
|
+
|
19
|
+
before { dispatcher.reset }
|
20
|
+
|
21
|
+
it "should add routes" do
|
22
|
+
expect {
|
23
|
+
dispatcher.add_route ['*'], resource
|
24
|
+
}.should_not raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should route to the proper resource" do
|
28
|
+
dispatcher.add_route ["goodbye"], resource2
|
29
|
+
dispatcher.add_route ['*'], resource
|
30
|
+
Webmachine::Decision::FSM.should_receive(:new).with(instance_of(resource), request, response).and_return(fsm)
|
31
|
+
fsm.should_receive(:run)
|
32
|
+
dispatcher.dispatch(request, response)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Webmachine::Headers do
|
4
|
+
it "should set and access values insensitive to case" do
|
5
|
+
subject['Content-TYPE'] = "text/plain"
|
6
|
+
subject['CONTENT-TYPE'].should == 'text/plain'
|
7
|
+
end
|
8
|
+
|
9
|
+
context "filtering with #grep" do
|
10
|
+
subject { described_class["content-type" => "text/plain", "etag" => '"abcdef1234567890"'] }
|
11
|
+
it "should filter keys by the given pattern" do
|
12
|
+
subject.grep(/content/i).should include("content-type")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return a Headers instance" do
|
16
|
+
subject.grep(/etag/i).should be_instance_of(described_class)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Webmachine::Request do
|
4
|
+
subject { Webmachine::Request.new("GET", URI.parse("http://localhost:8080/some/resource"), Webmachine::Headers.new, "") }
|
5
|
+
it "should provide access to the headers via brackets" do
|
6
|
+
subject.headers['Accept'] = "*/*"
|
7
|
+
subject["accept"].should == "*/*"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should provide access to the headers via underscored methods" do
|
11
|
+
subject.headers["Accept-Encoding"] = "identity"
|
12
|
+
subject.accept_encoding.should == "identity"
|
13
|
+
subject.content_md5.should be_nil
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should calculate a base URI" do
|
17
|
+
subject.base_uri.should == URI.parse("http://localhost:8080/")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should provide a hash of query parameters" do
|
21
|
+
subject.uri.query = "foo=bar&baz=bam"
|
22
|
+
subject.query.should == {"foo" => "bar", "baz" => "bam"}
|
23
|
+
end
|
24
|
+
end
|
data/webmachine.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require 'webmachine/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = "webmachine"
|
6
|
+
gem.version = Webmachine::VERSION
|
7
|
+
gem.date = File.mtime("lib/webmachine/version.rb")
|
8
|
+
gem.summary = %Q{webmachine is a toolkit for building HTTP applications,}
|
9
|
+
gem.description = <<-DESC.gsub(/\s+/, ' ')
|
10
|
+
webmachine is a toolkit for building HTTP applications in a declarative fashion, that avoids
|
11
|
+
the confusion of going through a CGI-style interface like Rack. It is strongly influenced
|
12
|
+
by the original Erlang project of the same name and shares its opinionated nature about HTTP.
|
13
|
+
DESC
|
14
|
+
gem.homepage = "http://seancribbs.github.com/webmachine.rb"
|
15
|
+
gem.authors = ["Sean Cribbs"]
|
16
|
+
gem.email = ["sean@basho.com"]
|
17
|
+
|
18
|
+
if gem.respond_to? :specification_version then
|
19
|
+
gem.specification_version = 3
|
20
|
+
|
21
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
22
|
+
gem.add_runtime_dependency(%q<i18n>, [">= 0.4.0"])
|
23
|
+
gem.add_development_dependency(%q<rspec>, ["~> 2.6.0"])
|
24
|
+
gem.add_development_dependency(%q<yard>, ["~> 0.6.7"])
|
25
|
+
gem.add_development_dependency(%q<rake>)
|
26
|
+
else
|
27
|
+
gem.add_dependency(%q<i18n>, [">= 0.4.0"])
|
28
|
+
gem.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
29
|
+
gem.add_dependency(%q<yard>, ["~> 0.6.7"])
|
30
|
+
gem.add_dependency(%q<rake>)
|
31
|
+
end
|
32
|
+
else
|
33
|
+
gem.add_dependency(%q<i18n>, [">= 0.4.0"])
|
34
|
+
gem.add_dependency(%q<rspec>, ["~> 2.6.0"])
|
35
|
+
gem.add_dependency(%q<yard>, ["~> 0.6.7"])
|
36
|
+
gem.add_dependency(%q<rake>)
|
37
|
+
end
|
38
|
+
|
39
|
+
ignores = File.read(".gitignore").split(/\r?\n/).reject{ |f| f =~ /^(#.+|\s*)$/ }.map {|f| Dir[f] }.flatten
|
40
|
+
gem.files = (Dir['**/*','.gitignore'] - ignores).reject {|f| !File.file?(f) }
|
41
|
+
gem.test_files = (Dir['spec/**/*','features/**/*','.gitignore'] - ignores).reject {|f| !File.file?(f) }
|
42
|
+
gem.executables = Dir['bin/*'].map { |f| File.basename(f) }
|
43
|
+
gem.require_paths = ['lib']
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: webmachine
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sean Cribbs
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-25 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: i18n
|
16
|
+
requirement: &2152637280 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.4.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152637280
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &2152636780 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.6.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2152636780
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: yard
|
38
|
+
requirement: &2152636300 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.6.7
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2152636300
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: &2152635920 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2152635920
|
58
|
+
description: ! ' webmachine is a toolkit for building HTTP applications in a declarative
|
59
|
+
fashion, that avoids the confusion of going through a CGI-style interface like Rack.
|
60
|
+
It is strongly influenced by the original Erlang project of the same name and shares
|
61
|
+
its opinionated nature about HTTP. '
|
62
|
+
email:
|
63
|
+
- sean@basho.com
|
64
|
+
executables: []
|
65
|
+
extensions: []
|
66
|
+
extra_rdoc_files: []
|
67
|
+
files:
|
68
|
+
- examples/webrick.rb
|
69
|
+
- Gemfile
|
70
|
+
- Guardfile
|
71
|
+
- lib/webmachine/adapters/webrick.rb
|
72
|
+
- lib/webmachine/adapters.rb
|
73
|
+
- lib/webmachine/decision/conneg.rb
|
74
|
+
- lib/webmachine/decision/flow.rb
|
75
|
+
- lib/webmachine/decision/fsm.rb
|
76
|
+
- lib/webmachine/decision/helpers.rb
|
77
|
+
- lib/webmachine/decision.rb
|
78
|
+
- lib/webmachine/dispatcher/route.rb
|
79
|
+
- lib/webmachine/dispatcher.rb
|
80
|
+
- lib/webmachine/errors.rb
|
81
|
+
- lib/webmachine/headers.rb
|
82
|
+
- lib/webmachine/locale/en.yml
|
83
|
+
- lib/webmachine/request.rb
|
84
|
+
- lib/webmachine/resource/callbacks.rb
|
85
|
+
- lib/webmachine/resource/encodings.rb
|
86
|
+
- lib/webmachine/resource.rb
|
87
|
+
- lib/webmachine/response.rb
|
88
|
+
- lib/webmachine/streaming.rb
|
89
|
+
- lib/webmachine/translation.rb
|
90
|
+
- lib/webmachine/version.rb
|
91
|
+
- lib/webmachine.rb
|
92
|
+
- Rakefile
|
93
|
+
- README.md
|
94
|
+
- spec/spec_helper.rb
|
95
|
+
- spec/tests.org
|
96
|
+
- spec/webmachine/decision/conneg_spec.rb
|
97
|
+
- spec/webmachine/decision/flow_spec.rb
|
98
|
+
- spec/webmachine/dispatcher/route_spec.rb
|
99
|
+
- spec/webmachine/dispatcher_spec.rb
|
100
|
+
- spec/webmachine/headers_spec.rb
|
101
|
+
- spec/webmachine/request_spec.rb
|
102
|
+
- webmachine.gemspec
|
103
|
+
- .gitignore
|
104
|
+
homepage: http://seancribbs.github.com/webmachine.rb
|
105
|
+
licenses: []
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
|
+
none: false
|
118
|
+
requirements:
|
119
|
+
- - ! '>='
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 1.8.6
|
125
|
+
signing_key:
|
126
|
+
specification_version: 3
|
127
|
+
summary: webmachine is a toolkit for building HTTP applications,
|
128
|
+
test_files:
|
129
|
+
- spec/spec_helper.rb
|
130
|
+
- spec/tests.org
|
131
|
+
- spec/webmachine/decision/conneg_spec.rb
|
132
|
+
- spec/webmachine/decision/flow_spec.rb
|
133
|
+
- spec/webmachine/dispatcher/route_spec.rb
|
134
|
+
- spec/webmachine/dispatcher_spec.rb
|
135
|
+
- spec/webmachine/headers_spec.rb
|
136
|
+
- spec/webmachine/request_spec.rb
|
137
|
+
- .gitignore
|