webmachine 1.2.2 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +13 -11
- data/README.md +85 -89
- data/Rakefile +0 -1
- data/documentation/adapters.md +39 -0
- data/documentation/authentication-and-authorization.md +37 -0
- data/documentation/configurator.md +19 -0
- data/documentation/error-handling.md +86 -0
- data/documentation/examples.md +215 -0
- data/documentation/how-it-works.md +76 -0
- data/documentation/routes.md +97 -0
- data/documentation/validation.md +159 -0
- data/documentation/versioning-apis.md +74 -0
- data/documentation/visual-debugger.md +38 -0
- data/examples/application.rb +2 -2
- data/examples/debugger.rb +1 -1
- data/lib/webmachine.rb +3 -1
- data/lib/webmachine/adapter.rb +7 -13
- data/lib/webmachine/adapters.rb +1 -2
- data/lib/webmachine/adapters/httpkit.rb +74 -0
- data/lib/webmachine/adapters/lazy_request_body.rb +1 -2
- data/lib/webmachine/adapters/rack.rb +37 -21
- data/lib/webmachine/adapters/reel.rb +21 -23
- data/lib/webmachine/adapters/webrick.rb +16 -16
- data/lib/webmachine/application.rb +2 -2
- data/lib/webmachine/chunked_body.rb +3 -4
- data/lib/webmachine/constants.rb +75 -0
- data/lib/webmachine/decision/conneg.rb +12 -10
- data/lib/webmachine/decision/flow.rb +31 -21
- data/lib/webmachine/decision/fsm.rb +10 -18
- data/lib/webmachine/decision/helpers.rb +9 -37
- data/lib/webmachine/dispatcher.rb +13 -10
- data/lib/webmachine/dispatcher/route.rb +18 -8
- data/lib/webmachine/errors.rb +7 -1
- data/lib/webmachine/header_negotiation.rb +25 -0
- data/lib/webmachine/headers.rb +7 -2
- data/lib/webmachine/locale/en.yml +7 -5
- data/lib/webmachine/media_type.rb +10 -8
- data/lib/webmachine/request.rb +44 -15
- data/lib/webmachine/resource.rb +1 -1
- data/lib/webmachine/resource/callbacks.rb +6 -4
- data/lib/webmachine/spec/IO_response.body +1 -0
- data/lib/webmachine/spec/adapter_lint.rb +70 -36
- data/lib/webmachine/spec/test_resource.rb +10 -4
- data/lib/webmachine/streaming/fiber_encoder.rb +1 -5
- data/lib/webmachine/streaming/io_encoder.rb +6 -0
- data/lib/webmachine/trace.rb +1 -0
- data/lib/webmachine/trace/fsm.rb +20 -10
- data/lib/webmachine/trace/resource_proxy.rb +2 -0
- data/lib/webmachine/translation.rb +2 -1
- data/lib/webmachine/version.rb +3 -3
- data/memory_test.rb +37 -0
- data/spec/spec_helper.rb +9 -9
- data/spec/webmachine/adapter_spec.rb +14 -15
- data/spec/webmachine/adapters/httpkit_spec.rb +10 -0
- data/spec/webmachine/adapters/rack_spec.rb +6 -6
- data/spec/webmachine/adapters/reel_spec.rb +15 -11
- data/spec/webmachine/adapters/webrick_spec.rb +2 -2
- data/spec/webmachine/application_spec.rb +18 -17
- data/spec/webmachine/chunked_body_spec.rb +3 -3
- data/spec/webmachine/configuration_spec.rb +5 -5
- data/spec/webmachine/cookie_spec.rb +13 -13
- data/spec/webmachine/decision/conneg_spec.rb +48 -42
- data/spec/webmachine/decision/falsey_spec.rb +4 -4
- data/spec/webmachine/decision/flow_spec.rb +194 -144
- data/spec/webmachine/decision/fsm_spec.rb +17 -17
- data/spec/webmachine/decision/helpers_spec.rb +20 -20
- data/spec/webmachine/dispatcher/route_spec.rb +73 -27
- data/spec/webmachine/dispatcher_spec.rb +34 -24
- data/spec/webmachine/errors_spec.rb +1 -1
- data/spec/webmachine/etags_spec.rb +19 -19
- data/spec/webmachine/events_spec.rb +6 -6
- data/spec/webmachine/headers_spec.rb +14 -14
- data/spec/webmachine/media_type_spec.rb +36 -36
- data/spec/webmachine/request_spec.rb +33 -33
- data/spec/webmachine/resource/authentication_spec.rb +6 -6
- data/spec/webmachine/response_spec.rb +12 -12
- data/spec/webmachine/trace/fsm_spec.rb +8 -8
- data/spec/webmachine/trace/resource_proxy_spec.rb +9 -9
- data/spec/webmachine/trace/trace_store_spec.rb +5 -5
- data/spec/webmachine/trace_spec.rb +3 -3
- data/webmachine.gemspec +2 -6
- metadata +48 -206
- data/lib/webmachine/adapters/hatetepe.rb +0 -108
- data/lib/webmachine/adapters/mongrel.rb +0 -127
- data/lib/webmachine/dispatcher/not_found_resource.rb +0 -5
- data/lib/webmachine/fiber18.rb +0 -88
- data/spec/webmachine/adapters/hatetepe_spec.rb +0 -60
- data/spec/webmachine/adapters/mongrel_spec.rb +0 -16
@@ -1,39 +1,38 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Webmachine::Adapter do
|
4
|
-
let(:
|
5
|
-
let(:dispatcher) { Webmachine::Dispatcher.new }
|
4
|
+
let(:application) { Webmachine::Application.new }
|
6
5
|
let(:adapter) do
|
7
|
-
|
6
|
+
server = TCPServer.new('0.0.0.0', 0)
|
7
|
+
application.configuration.port = server.addr[1]
|
8
|
+
server.close
|
9
|
+
|
10
|
+
described_class.new(application)
|
8
11
|
end
|
9
12
|
|
10
13
|
describe "#initialize" do
|
11
|
-
it "stores the provided
|
12
|
-
adapter.
|
13
|
-
end
|
14
|
-
|
15
|
-
it "stores the provided dispatcher" do
|
16
|
-
adapter.dispatcher.should eql dispatcher
|
14
|
+
it "stores the provided application" do
|
15
|
+
expect(adapter.application).to eq(application)
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
19
|
describe ".run" do
|
21
20
|
it "creates a new adapter and runs it" do
|
22
|
-
adapter =
|
21
|
+
adapter = double(described_class)
|
23
22
|
|
24
|
-
described_class.
|
25
|
-
with(
|
23
|
+
expect(described_class).to receive(:new).
|
24
|
+
with(application).
|
26
25
|
and_return(adapter)
|
27
26
|
|
28
|
-
adapter.
|
27
|
+
expect(adapter).to receive(:run)
|
29
28
|
|
30
|
-
described_class.run(
|
29
|
+
described_class.run(application)
|
31
30
|
end
|
32
31
|
end
|
33
32
|
|
34
33
|
describe "#run" do
|
35
34
|
it "raises a NotImplementedError" do
|
36
|
-
|
35
|
+
expect { adapter.run }.to raise_exception(NotImplementedError)
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
@@ -7,30 +7,30 @@ describe Webmachine::Adapters::Rack do
|
|
7
7
|
it_should_behave_like :adapter_lint do
|
8
8
|
it "should set Server header" do
|
9
9
|
response = client.request(Net::HTTP::Get.new("/test"))
|
10
|
-
response["Server"].
|
11
|
-
response["Server"].
|
10
|
+
expect(response["Server"]).to match(/Webmachine/)
|
11
|
+
expect(response["Server"]).to match(/Rack/)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
describe Webmachine::Adapters::Rack::RackResponse do
|
17
17
|
context "on Rack < 1.5 release" do
|
18
|
-
before { Rack.
|
18
|
+
before { allow(Rack).to receive_messages(:release => "1.4") }
|
19
19
|
|
20
20
|
it "should add Content-Type header on not acceptable response" do
|
21
21
|
rack_response = described_class.new(double(:body), 406, {})
|
22
22
|
rack_status, rack_headers, rack_body = rack_response.finish
|
23
|
-
rack_headers.
|
23
|
+
expect(rack_headers).to have_key("Content-Type")
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
context "on Rack >= 1.5 release" do
|
28
|
-
before { Rack.
|
28
|
+
before { allow(Rack).to receive_messages(:release => "1.5") }
|
29
29
|
|
30
30
|
it "should not add Content-Type header on not acceptable response" do
|
31
31
|
rack_response = described_class.new(double(:body), 406, {})
|
32
32
|
rack_status, rack_headers, rack_body = rack_response.finish
|
33
|
-
rack_headers.
|
33
|
+
expect(rack_headers).not_to have_key("Content-Type")
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'webmachine/spec/adapter_lint'
|
3
3
|
describe Webmachine::Adapters::Reel do
|
4
|
-
|
5
|
-
|
6
|
-
let(:configuration) { Webmachine::Configuration.default }
|
7
|
-
let(:dispatcher) { Webmachine::Dispatcher.new }
|
8
|
-
let(:adapter) do
|
9
|
-
described_class.new(configuration, dispatcher)
|
4
|
+
context 'lint' do
|
5
|
+
it_should_behave_like :adapter_lint
|
10
6
|
end
|
11
7
|
|
12
8
|
context 'websockets' do
|
9
|
+
let(:application) { Webmachine::Application.new }
|
10
|
+
let(:adapter) do
|
11
|
+
server = TCPServer.new('0.0.0.0', 0)
|
12
|
+
application.configuration.port = server.addr[1]
|
13
|
+
server.close
|
14
|
+
described_class.new(application)
|
15
|
+
end
|
16
|
+
|
13
17
|
let(:example_host) { "www.example.com" }
|
14
18
|
let(:example_path) { "/example"}
|
15
19
|
let(:example_url) { "ws://#{example_host}#{example_path}" }
|
@@ -28,8 +32,8 @@ describe Webmachine::Adapters::Reel do
|
|
28
32
|
let(:server_message) { "Hi client!" }
|
29
33
|
|
30
34
|
it 'supports websockets' do
|
31
|
-
configuration.adapter_options[:websocket_handler] = proc do |socket|
|
32
|
-
socket.read.
|
35
|
+
application.configuration.adapter_options[:websocket_handler] = proc do |socket|
|
36
|
+
expect(socket.read).to eq client_message
|
33
37
|
socket << server_message
|
34
38
|
end
|
35
39
|
|
@@ -44,7 +48,7 @@ describe Webmachine::Adapters::Reel do
|
|
44
48
|
parser = WebSocket::Parser.new
|
45
49
|
parser.append client.readpartial(4096) until message = parser.next_message
|
46
50
|
|
47
|
-
message.
|
51
|
+
expect(message).to eq server_message
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -54,7 +58,7 @@ describe Webmachine::Adapters::Reel do
|
|
54
58
|
begin
|
55
59
|
timeout(5) do
|
56
60
|
begin
|
57
|
-
sock = TCPSocket.new(adptr.configuration.ip, adptr.configuration.port)
|
61
|
+
sock = TCPSocket.new(adptr.application.configuration.ip, adptr.application.configuration.port)
|
58
62
|
begin
|
59
63
|
yield(sock)
|
60
64
|
ensure
|
@@ -66,7 +70,7 @@ describe Webmachine::Adapters::Reel do
|
|
66
70
|
end
|
67
71
|
end
|
68
72
|
ensure
|
69
|
-
|
73
|
+
thread.kill if thread
|
70
74
|
end
|
71
75
|
end
|
72
76
|
end
|
@@ -5,8 +5,8 @@ describe Webmachine::Adapters::WEBrick do
|
|
5
5
|
it_should_behave_like :adapter_lint do
|
6
6
|
it "should set Server header" do
|
7
7
|
response = client.request(Net::HTTP::Get.new("/test"))
|
8
|
-
response["Server"].
|
9
|
-
response["Server"].
|
8
|
+
expect(response["Server"]).to match(/Webmachine/)
|
9
|
+
expect(response["Server"]).to match(/WEBrick/)
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -5,69 +5,70 @@ describe Webmachine::Application do
|
|
5
5
|
let(:test_resource) { Class.new(Webmachine::Resource) }
|
6
6
|
|
7
7
|
it "accepts a Configuration when initialized" do
|
8
|
-
config = Webmachine::Configuration.new('1.1.1.1', 9999, :
|
9
|
-
described_class.new(config).configuration.
|
8
|
+
config = Webmachine::Configuration.new('1.1.1.1', 9999, :Reel, {})
|
9
|
+
expect(described_class.new(config).configuration).to be(config)
|
10
10
|
end
|
11
11
|
|
12
12
|
it "is yielded into a block provided during initialization" do
|
13
13
|
yielded_app = nil
|
14
|
-
described_class.new do |app|
|
15
|
-
app.
|
14
|
+
returned_app = described_class.new do |app|
|
15
|
+
expect(app).to be_kind_of(Webmachine::Application)
|
16
16
|
yielded_app = app
|
17
|
-
end
|
17
|
+
end
|
18
|
+
expect(returned_app).to be(yielded_app)
|
18
19
|
end
|
19
20
|
|
20
21
|
it "is initialized with the default Configration if none is given" do
|
21
|
-
application.configuration.
|
22
|
+
expect(application.configuration).to eq(Webmachine::Configuration.default)
|
22
23
|
end
|
23
24
|
|
24
25
|
it "returns the receiver from the configure call so you can chain it" do
|
25
|
-
application.configure { |c| }.
|
26
|
+
expect(application.configure { |c| }).to equal(application)
|
26
27
|
end
|
27
28
|
|
28
29
|
it "is configurable" do
|
29
30
|
application.configure do |config|
|
30
|
-
config.
|
31
|
+
expect(config).to be_kind_of(Webmachine::Configuration)
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
34
35
|
it "is initialized with an empty Dispatcher" do
|
35
|
-
application.dispatcher.routes.
|
36
|
+
expect(application.dispatcher.routes).to be_empty
|
36
37
|
end
|
37
38
|
|
38
39
|
it "can have routes added" do
|
39
40
|
route = nil
|
40
41
|
resource = test_resource # overcome instance_eval :/
|
41
42
|
|
42
|
-
application.routes.
|
43
|
+
expect(application.routes).to be_empty
|
43
44
|
|
44
45
|
application.routes do
|
45
|
-
route = add [
|
46
|
+
route = add [:*], resource
|
46
47
|
end
|
47
48
|
|
48
|
-
route.
|
49
|
-
application.routes.
|
49
|
+
expect(route).to be_kind_of(Webmachine::Dispatcher::Route)
|
50
|
+
expect(application.routes).to eq([route])
|
50
51
|
end
|
51
52
|
|
52
53
|
describe "#adapter" do
|
53
54
|
let(:adapter_class) { application.adapter_class }
|
54
55
|
|
55
56
|
it "returns an instance of it's adapter class" do
|
56
|
-
application.adapter.
|
57
|
+
expect(application.adapter).to be_an_instance_of(adapter_class)
|
57
58
|
end
|
58
59
|
|
59
60
|
it "is memoized" do
|
60
|
-
application.adapter.
|
61
|
+
expect(application.adapter).to eql application.adapter
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
64
65
|
it "can be run" do
|
65
|
-
application.adapter.
|
66
|
+
expect(application.adapter).to receive(:run)
|
66
67
|
application.run
|
67
68
|
end
|
68
69
|
|
69
70
|
it "can be queried about its configured adapter" do
|
70
71
|
expected = Webmachine::Adapters.const_get(application.configuration.adapter)
|
71
|
-
application.adapter_class.
|
72
|
+
expect(application.adapter_class).to equal(expected)
|
72
73
|
end
|
73
74
|
end
|
@@ -7,7 +7,7 @@ describe Webmachine::ChunkedBody do
|
|
7
7
|
Webmachine::ChunkedBody.new(['foo', 'bar', '', 'j', 'webmachine']).each do |chunk|
|
8
8
|
body << chunk
|
9
9
|
end
|
10
|
-
body.
|
10
|
+
expect(body).to eq("3\r\nfoo\r\n3\r\nbar\r\n1\r\nj\r\na\r\nwebmachine\r\n0\r\n\r\n")
|
11
11
|
end
|
12
12
|
|
13
13
|
context "with an empty body" do
|
@@ -16,14 +16,14 @@ describe Webmachine::ChunkedBody do
|
|
16
16
|
Webmachine::ChunkedBody.new([]).each do |chunk|
|
17
17
|
body << chunk
|
18
18
|
end
|
19
|
-
body.
|
19
|
+
expect(body).to eq("0\r\n\r\n")
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
describe "#each" do
|
24
24
|
context "without a block given" do
|
25
25
|
it "returns an Enumerator" do
|
26
|
-
Webmachine::ChunkedBody.new([]).each.
|
26
|
+
expect(Webmachine::ChunkedBody.new([]).each).to respond_to(:next)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -4,13 +4,13 @@ describe Webmachine::Configuration do
|
|
4
4
|
before { Webmachine.configuration = nil }
|
5
5
|
|
6
6
|
%w{ip port adapter adapter_options}.each do |field|
|
7
|
-
it {
|
8
|
-
it {
|
7
|
+
it { is_expected.to respond_to(field) }
|
8
|
+
it { is_expected.to respond_to("#{field}=") }
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should yield configuration to the block" do
|
12
12
|
Webmachine.configure do |config|
|
13
|
-
config.
|
13
|
+
expect(config).to be_kind_of(described_class)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -18,10 +18,10 @@ describe Webmachine::Configuration do
|
|
18
18
|
Webmachine.configure do |config|
|
19
19
|
@config = config
|
20
20
|
end
|
21
|
-
@config.
|
21
|
+
expect(@config).to eq Webmachine.configuration
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should return the module from the configure call so you can chain it" do
|
25
|
-
Webmachine.configure {|c|}.
|
25
|
+
expect(Webmachine.configure {|c|}).to eq Webmachine
|
26
26
|
end
|
27
27
|
end
|
@@ -53,14 +53,14 @@ describe Webmachine::Cookie do
|
|
53
53
|
|
54
54
|
it "should include the attributes in its string version" do
|
55
55
|
str = subject.to_s
|
56
|
-
str.
|
57
|
-
str.
|
58
|
-
str.
|
59
|
-
str.
|
60
|
-
str.
|
61
|
-
str.
|
62
|
-
str.
|
63
|
-
str.
|
56
|
+
expect(str).to include "Secure"
|
57
|
+
expect(str).to include "HttpOnly"
|
58
|
+
expect(str).to include "Comment=comment+with+spaces"
|
59
|
+
expect(str).to include "Domain=www.server.com"
|
60
|
+
expect(str).to include "Path=/"
|
61
|
+
expect(str).to include "Version=1"
|
62
|
+
expect(str).to include "Max-Age=60"
|
63
|
+
expect(str).to include "Expires=Sun, 14-Mar-2010 03:14:00 GMT"
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -70,30 +70,30 @@ describe Webmachine::Cookie do
|
|
70
70
|
|
71
71
|
subject { Webmachine::Cookie.parse(str) }
|
72
72
|
|
73
|
-
it("should have the cookie") { subject.
|
73
|
+
it("should have the cookie") { expect(subject).to eq({ "cookie" => "monster" }) }
|
74
74
|
|
75
75
|
describe "parsing multiple cookie parameters" do
|
76
76
|
let(:str) { "cookie=monster; monster=mash" }
|
77
77
|
|
78
|
-
it("should have both cookies") { subject.
|
78
|
+
it("should have both cookies") { expect(subject).to eq({ "cookie" => "monster", "monster" => "mash" }) }
|
79
79
|
end
|
80
80
|
|
81
81
|
describe "parsing an encoded cookie" do
|
82
82
|
let(:str) { "cookie=yum+yum" }
|
83
83
|
|
84
|
-
it("should decode the cookie") { subject.
|
84
|
+
it("should decode the cookie") { expect(subject).to eq({ "cookie" => "yum yum" }) }
|
85
85
|
end
|
86
86
|
|
87
87
|
describe "parsing nil" do
|
88
88
|
let(:str) { nil }
|
89
89
|
|
90
|
-
it("should return empty hash") { subject.
|
90
|
+
it("should return empty hash") { expect(subject).to eq({}) }
|
91
91
|
end
|
92
92
|
|
93
93
|
describe "parsing duplicate cookies" do
|
94
94
|
let(:str) { "cookie=monster; cookie=yum+yum" }
|
95
95
|
|
96
|
-
it("should return the first instance of the cookie") { subject.
|
96
|
+
it("should return the first instance of the cookie") { expect(subject).to eq({ "cookie" => "monster" }) }
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
@@ -9,35 +9,35 @@ describe Webmachine::Decision::Conneg do
|
|
9
9
|
|
10
10
|
context "choosing a media type" do
|
11
11
|
it "should not choose a type when none are provided" do
|
12
|
-
subject.choose_media_type([], "*/*").
|
12
|
+
expect(subject.choose_media_type([], "*/*")).to be_nil
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should not choose a type when none are acceptable" do
|
16
|
-
subject.choose_media_type(["text/html"], "application/json").
|
16
|
+
expect(subject.choose_media_type(["text/html"], "application/json")).to be_nil
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should choose the first acceptable type" do
|
20
|
-
subject.choose_media_type(["text/html", "application/xml"],
|
21
|
-
"application/xml, text/html, */*").
|
20
|
+
expect(subject.choose_media_type(["text/html", "application/xml"],
|
21
|
+
"application/xml, text/html, */*")).to eq("application/xml")
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should choose the type that matches closest when matching subparams" do
|
25
|
-
subject.choose_media_type(["text/html",
|
25
|
+
expect(subject.choose_media_type(["text/html",
|
26
26
|
["text/html", {"charset" => "iso8859-1"}]],
|
27
|
-
"text/html;charset=iso8859-1, application/xml").
|
28
|
-
|
27
|
+
"text/html;charset=iso8859-1, application/xml")).
|
28
|
+
to eq("text/html;charset=iso8859-1")
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should choose a type more specific than requested when an exact match is not present" do
|
32
|
-
subject.choose_media_type(["application/json;v=3;foo=bar", "application/json;v=2"],
|
33
|
-
"text/html, application/json").
|
34
|
-
|
32
|
+
expect(subject.choose_media_type(["application/json;v=3;foo=bar", "application/json;v=2"],
|
33
|
+
"text/html, application/json")).
|
34
|
+
to eq("application/json;v=3;foo=bar")
|
35
35
|
end
|
36
36
|
|
37
37
|
|
38
38
|
it "should choose the preferred type over less-preferred types" do
|
39
|
-
subject.choose_media_type(["text/html", "application/xml"],
|
40
|
-
"application/xml;q=0.7, text/html, */*").
|
39
|
+
expect(subject.choose_media_type(["text/html", "application/xml"],
|
40
|
+
"application/xml;q=0.7, text/html, */*")).to eq("text/html")
|
41
41
|
|
42
42
|
end
|
43
43
|
|
@@ -47,114 +47,120 @@ describe Webmachine::Decision::Conneg do
|
|
47
47
|
"bah;")
|
48
48
|
}.to raise_error(Webmachine::MalformedRequest)
|
49
49
|
end
|
50
|
+
|
51
|
+
it "should choose a type when more than one accept header is present" do
|
52
|
+
expect(subject.choose_media_type(["text/html"],
|
53
|
+
["text/html", "text/plain"])).to eq("text/html")
|
54
|
+
|
55
|
+
end
|
50
56
|
end
|
51
57
|
|
52
58
|
context "choosing an encoding" do
|
53
59
|
it "should not set the encoding when none are provided" do
|
54
60
|
subject.choose_encoding({}, "identity, gzip")
|
55
|
-
subject.metadata['Content-Encoding'].
|
56
|
-
subject.response.headers['Content-Encoding'].
|
61
|
+
expect(subject.metadata['Content-Encoding']).to be_nil
|
62
|
+
expect(subject.response.headers['Content-Encoding']).to be_nil
|
57
63
|
end
|
58
64
|
|
59
65
|
it "should not set the Content-Encoding header when it is identity" do
|
60
66
|
subject.choose_encoding({"gzip"=> :encode_gzip, "identity" => :encode_identity}, "identity")
|
61
|
-
subject.metadata['Content-Encoding'].
|
62
|
-
response.headers['Content-Encoding'].
|
67
|
+
expect(subject.metadata['Content-Encoding']).to eq('identity')
|
68
|
+
expect(response.headers['Content-Encoding']).to be_nil
|
63
69
|
end
|
64
70
|
|
65
71
|
it "should choose the first acceptable encoding" do
|
66
72
|
subject.choose_encoding({"gzip" => :encode_gzip}, "identity, gzip")
|
67
|
-
subject.metadata['Content-Encoding'].
|
68
|
-
response.headers['Content-Encoding'].
|
73
|
+
expect(subject.metadata['Content-Encoding']).to eq('gzip')
|
74
|
+
expect(response.headers['Content-Encoding']).to eq('gzip')
|
69
75
|
end
|
70
76
|
|
71
77
|
it "should choose the first acceptable encoding" \
|
72
78
|
", even when no white space after comma" do
|
73
79
|
subject.choose_encoding({"gzip" => :encode_gzip}, "identity,gzip")
|
74
|
-
subject.metadata['Content-Encoding'].
|
75
|
-
response.headers['Content-Encoding'].
|
80
|
+
expect(subject.metadata['Content-Encoding']).to eq('gzip')
|
81
|
+
expect(response.headers['Content-Encoding']).to eq('gzip')
|
76
82
|
end
|
77
83
|
|
78
84
|
it "should choose the preferred encoding over less-preferred encodings" do
|
79
85
|
subject.choose_encoding({"gzip" => :encode_gzip, "identity" => :encode_identity}, "gzip, identity;q=0.7")
|
80
|
-
subject.metadata['Content-Encoding'].
|
81
|
-
response.headers['Content-Encoding'].
|
86
|
+
expect(subject.metadata['Content-Encoding']).to eq('gzip')
|
87
|
+
expect(response.headers['Content-Encoding']).to eq('gzip')
|
82
88
|
end
|
83
89
|
|
84
90
|
it "should not set the encoding if none are acceptable" do
|
85
91
|
subject.choose_encoding({"gzip" => :encode_gzip}, "identity")
|
86
|
-
subject.metadata['Content-Encoding'].
|
87
|
-
response.headers['Content-Encoding'].
|
92
|
+
expect(subject.metadata['Content-Encoding']).to be_nil
|
93
|
+
expect(response.headers['Content-Encoding']).to be_nil
|
88
94
|
end
|
89
95
|
end
|
90
96
|
|
91
97
|
context "choosing a charset" do
|
92
98
|
it "should not set the charset when none are provided" do
|
93
99
|
subject.choose_charset([], "ISO-8859-1")
|
94
|
-
subject.metadata['Charset'].
|
100
|
+
expect(subject.metadata['Charset']).to be_nil
|
95
101
|
end
|
96
102
|
|
97
103
|
it "should choose the first acceptable charset" do
|
98
104
|
subject.choose_charset([["UTF-8", :to_utf8],["US-ASCII", :to_ascii]], "US-ASCII, UTF-8")
|
99
|
-
subject.metadata['Charset'].
|
105
|
+
expect(subject.metadata['Charset']).to eq("US-ASCII")
|
100
106
|
end
|
101
107
|
|
102
108
|
it "should choose the preferred charset over less-preferred charsets" do
|
103
109
|
subject.choose_charset([["UTF-8", :to_utf8],["US-ASCII", :to_ascii]], "US-ASCII;q=0.7, UTF-8")
|
104
|
-
subject.metadata['Charset'].
|
110
|
+
expect(subject.metadata['Charset']).to eq("UTF-8")
|
105
111
|
end
|
106
112
|
|
107
113
|
it "should not set the charset if none are acceptable" do
|
108
114
|
subject.choose_charset([["UTF-8", :to_utf8],["US-ASCII", :to_ascii]], "ISO-8859-1")
|
109
|
-
subject.metadata['Charset'].
|
115
|
+
expect(subject.metadata['Charset']).to be_nil
|
110
116
|
end
|
111
117
|
|
112
118
|
it "should choose a charset case-insensitively" do
|
113
119
|
subject.choose_charset([["UtF-8", :to_utf8],["US-ASCII", :to_ascii]], "iso-8859-1, utf-8")
|
114
|
-
subject.metadata['Charset'].
|
120
|
+
expect(subject.metadata['Charset']).to eq("utf-8")
|
115
121
|
end
|
116
122
|
end
|
117
123
|
|
118
124
|
context "choosing a language" do
|
119
125
|
it "should not set the language when none are provided" do
|
120
126
|
subject.choose_language([], "en")
|
121
|
-
subject.metadata['Language'].
|
127
|
+
expect(subject.metadata['Language']).to be_nil
|
122
128
|
end
|
123
129
|
|
124
130
|
it "should choose the first acceptable language" do
|
125
131
|
subject.choose_language(['en', 'en-US', 'es'], "en-US, es")
|
126
|
-
subject.metadata['Language'].
|
127
|
-
response.headers['Content-Language'].
|
132
|
+
expect(subject.metadata['Language']).to eq("en-US")
|
133
|
+
expect(response.headers['Content-Language']).to eq("en-US")
|
128
134
|
end
|
129
135
|
|
130
136
|
it "should choose the preferred language over less-preferred languages" do
|
131
137
|
subject.choose_language(['en', 'en-US', 'es'], "en-US;q=0.6, es")
|
132
|
-
subject.metadata['Language'].
|
133
|
-
response.headers['Content-Language'].
|
138
|
+
expect(subject.metadata['Language']).to eq("es")
|
139
|
+
expect(response.headers['Content-Language']).to eq("es")
|
134
140
|
end
|
135
141
|
|
136
142
|
it "should select the first language if all are acceptable" do
|
137
143
|
subject.choose_language(['en', 'fr', 'es'], "*")
|
138
|
-
subject.metadata['Language'].
|
139
|
-
response.headers['Content-Language'].
|
144
|
+
expect(subject.metadata['Language']).to eq("en")
|
145
|
+
expect(response.headers['Content-Language']).to eq("en")
|
140
146
|
end
|
141
147
|
|
142
148
|
it "should select the closest acceptable language when an exact match is not available" do
|
143
149
|
subject.choose_language(['en-US', 'es'], "en, fr")
|
144
|
-
subject.metadata['Language'].
|
145
|
-
response.headers['Content-Language'].
|
150
|
+
expect(subject.metadata['Language']).to eq('en-US')
|
151
|
+
expect(response.headers['Content-Language']).to eq('en-US')
|
146
152
|
end
|
147
153
|
|
148
154
|
it "should not set the language if none are acceptable" do
|
149
155
|
subject.choose_language(['en'], 'es')
|
150
|
-
subject.metadata['Language'].
|
151
|
-
response.headers.
|
156
|
+
expect(subject.metadata['Language']).to be_nil
|
157
|
+
expect(response.headers).not_to include('Content-Language')
|
152
158
|
end
|
153
159
|
|
154
160
|
it "should choose a language case-insensitively" do
|
155
161
|
subject.choose_language(['en-US', 'ZH'], 'zh-ch, EN')
|
156
|
-
subject.metadata['Language'].
|
157
|
-
response.headers['Content-Language'].
|
162
|
+
expect(subject.metadata['Language']).to eq('en-US')
|
163
|
+
expect(response.headers['Content-Language']).to eq('en-US')
|
158
164
|
end
|
159
165
|
end
|
160
166
|
end
|