astrotrain 0.3.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/.gitignore +26 -0
- data/LICENSE +20 -0
- data/README +47 -0
- data/Rakefile +122 -0
- data/VERSION +1 -0
- data/astrotrain.gemspec +129 -0
- data/config/sample.rb +12 -0
- data/lib/astrotrain.rb +53 -0
- data/lib/astrotrain/api.rb +52 -0
- data/lib/astrotrain/logged_mail.rb +46 -0
- data/lib/astrotrain/mapping.rb +157 -0
- data/lib/astrotrain/mapping/http_post.rb +18 -0
- data/lib/astrotrain/mapping/jabber.rb +28 -0
- data/lib/astrotrain/mapping/transport.rb +55 -0
- data/lib/astrotrain/message.rb +330 -0
- data/lib/astrotrain/tmail.rb +58 -0
- data/lib/astrotrain/worker.rb +65 -0
- data/lib/vendor/rest-client/README.rdoc +104 -0
- data/lib/vendor/rest-client/Rakefile +84 -0
- data/lib/vendor/rest-client/bin/restclient +65 -0
- data/lib/vendor/rest-client/foo.diff +66 -0
- data/lib/vendor/rest-client/lib/rest_client.rb +188 -0
- data/lib/vendor/rest-client/lib/rest_client/net_http_ext.rb +23 -0
- data/lib/vendor/rest-client/lib/rest_client/payload.rb +185 -0
- data/lib/vendor/rest-client/lib/rest_client/request_errors.rb +75 -0
- data/lib/vendor/rest-client/lib/rest_client/resource.rb +103 -0
- data/lib/vendor/rest-client/rest-client.gemspec +18 -0
- data/lib/vendor/rest-client/spec/base.rb +5 -0
- data/lib/vendor/rest-client/spec/master_shake.jpg +0 -0
- data/lib/vendor/rest-client/spec/payload_spec.rb +71 -0
- data/lib/vendor/rest-client/spec/request_errors_spec.rb +44 -0
- data/lib/vendor/rest-client/spec/resource_spec.rb +52 -0
- data/lib/vendor/rest-client/spec/rest_client_spec.rb +219 -0
- data/test/api_test.rb +28 -0
- data/test/fixtures/apple_multipart.txt +100 -0
- data/test/fixtures/bad_content_type.txt +27 -0
- data/test/fixtures/basic.txt +14 -0
- data/test/fixtures/custom.txt +15 -0
- data/test/fixtures/fwd.txt +0 -0
- data/test/fixtures/gb2312_encoding.txt +16 -0
- data/test/fixtures/gb2312_encoding_invalid.txt +15 -0
- data/test/fixtures/html.txt +16 -0
- data/test/fixtures/iso-8859-1.txt +13 -0
- data/test/fixtures/mapped.txt +13 -0
- data/test/fixtures/multipart.txt +213 -0
- data/test/fixtures/multipart2.txt +213 -0
- data/test/fixtures/multiple.txt +13 -0
- data/test/fixtures/multiple_delivered_to.txt +14 -0
- data/test/fixtures/multiple_with_body_recipients.txt +15 -0
- data/test/fixtures/reply.txt +16 -0
- data/test/fixtures/utf-8.txt +13 -0
- data/test/logged_mail_test.rb +67 -0
- data/test/mapping_test.rb +129 -0
- data/test/message_test.rb +440 -0
- data/test/test_helper.rb +57 -0
- data/test/transport_test.rb +111 -0
- metadata +225 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
module RestClient
|
2
|
+
# A class that can be instantiated for access to a RESTful resource,
|
3
|
+
# including authentication.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
#
|
7
|
+
# resource = RestClient::Resource.new('http://some/resource')
|
8
|
+
# jpg = resource.get(:accept => 'image/jpg')
|
9
|
+
#
|
10
|
+
# With HTTP basic authentication:
|
11
|
+
#
|
12
|
+
# resource = RestClient::Resource.new('http://protected/resource', 'user', 'pass')
|
13
|
+
# resource.delete
|
14
|
+
#
|
15
|
+
# Use the [] syntax to allocate subresources:
|
16
|
+
#
|
17
|
+
# site = RestClient::Resource.new('http://example.com', 'adam', 'mypasswd')
|
18
|
+
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
19
|
+
#
|
20
|
+
class Resource
|
21
|
+
attr_reader :url, :user, :password
|
22
|
+
|
23
|
+
def initialize(url, user=nil, password=nil)
|
24
|
+
@url = url
|
25
|
+
@user = user
|
26
|
+
@password = password
|
27
|
+
end
|
28
|
+
|
29
|
+
def get(headers={}, &b)
|
30
|
+
Request.execute(:method => :get,
|
31
|
+
:url => url,
|
32
|
+
:user => user,
|
33
|
+
:password => password,
|
34
|
+
:headers => headers, &b)
|
35
|
+
end
|
36
|
+
|
37
|
+
def post(payload, headers={}, &b)
|
38
|
+
Request.execute(:method => :post,
|
39
|
+
:url => url,
|
40
|
+
:payload => payload,
|
41
|
+
:user => user,
|
42
|
+
:password => password,
|
43
|
+
:headers => headers, &b)
|
44
|
+
end
|
45
|
+
|
46
|
+
def put(payload, headers={}, &b)
|
47
|
+
Request.execute(:method => :put,
|
48
|
+
:url => url,
|
49
|
+
:payload => payload,
|
50
|
+
:user => user,
|
51
|
+
:password => password,
|
52
|
+
:headers => headers, &b)
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete(headers={}, &b)
|
56
|
+
Request.execute(:method => :delete,
|
57
|
+
:url => url,
|
58
|
+
:user => user,
|
59
|
+
:password => password,
|
60
|
+
:headers => headers, &b)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Construct a subresource, preserving authentication.
|
64
|
+
#
|
65
|
+
# Example:
|
66
|
+
#
|
67
|
+
# site = RestClient::Resource.new('http://example.com', 'adam', 'mypasswd')
|
68
|
+
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
69
|
+
#
|
70
|
+
# This is especially useful if you wish to define your site in one place and
|
71
|
+
# call it in multiple locations:
|
72
|
+
#
|
73
|
+
# def orders
|
74
|
+
# RestClient::Resource.new('http://example.com/orders', 'admin', 'mypasswd')
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# orders.get # GET http://example.com/orders
|
78
|
+
# orders['1'].get # GET http://example.com/orders/1
|
79
|
+
# orders['1/items'].delete # DELETE http://example.com/orders/1/items
|
80
|
+
#
|
81
|
+
# Nest resources as far as you want:
|
82
|
+
#
|
83
|
+
# site = RestClient::Resource.new('http://example.com')
|
84
|
+
# posts = site['posts']
|
85
|
+
# first_post = posts['1']
|
86
|
+
# comments = first_post['comments']
|
87
|
+
# comments.post 'Hello', :content_type => 'text/plain'
|
88
|
+
#
|
89
|
+
def [](suburl)
|
90
|
+
self.class.new(concat_urls(url, suburl), user, password)
|
91
|
+
end
|
92
|
+
|
93
|
+
def concat_urls(url, suburl) # :nodoc:
|
94
|
+
url = url.to_s
|
95
|
+
suburl = suburl.to_s
|
96
|
+
if url.slice(-1, 1) == '/' or suburl.slice(0, 1) == '/'
|
97
|
+
url + suburl
|
98
|
+
else
|
99
|
+
"#{url}/#{suburl}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "rest-client"
|
3
|
+
s.version = "0.6.2"
|
4
|
+
s.summary = "Simple REST client for Ruby, inspired by microframework syntax for specifying actions."
|
5
|
+
s.description = "A simple REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete."
|
6
|
+
s.author = "Adam Wiggins"
|
7
|
+
s.email = "adam@heroku.com"
|
8
|
+
s.rubyforge_project = "rest-client"
|
9
|
+
s.homepage = "http://rest-client.heroku.com/"
|
10
|
+
s.has_rdoc = true
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.files = %w(Rakefile README.rdoc rest-client.gemspec
|
13
|
+
lib/request_errors.rb lib/resource.rb lib/rest_client.rb
|
14
|
+
spec/base.rb spec/request_errors_spec.rb spec/resource_spec.rb spec/rest_client_spec.rb
|
15
|
+
bin/restclient)
|
16
|
+
s.executables = ['restclient']
|
17
|
+
s.require_path = "lib"
|
18
|
+
end
|
Binary file
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/base"
|
2
|
+
|
3
|
+
describe RestClient::Payload do
|
4
|
+
context "A regular Payload" do
|
5
|
+
it "should should default content-type to standard enctype" do
|
6
|
+
RestClient::Payload::UrlEncoded.new({}).headers['Content-Type'].
|
7
|
+
should == 'application/x-www-form-urlencoded'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should form properly encoded params" do
|
11
|
+
RestClient::Payload::UrlEncoded.new({:foo => 'bar'}).to_s.
|
12
|
+
should == "foo=bar"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "A multipart Payload" do
|
17
|
+
it "should should default content-type to standard enctype" do
|
18
|
+
m = RestClient::Payload::Multipart.new({})
|
19
|
+
m.stub!(:boundary).and_return(123)
|
20
|
+
m.headers['Content-Type'].should == 'multipart/form-data; boundary="123"'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should form properly seperated multipart data" do
|
24
|
+
m = RestClient::Payload::Multipart.new({:foo => "bar", :bar => 'foo'})
|
25
|
+
m.to_s.should == <<-EOS
|
26
|
+
--#{m.boundary}\r
|
27
|
+
Content-Disposition: multipart/form-data; name="bar"\r
|
28
|
+
\r
|
29
|
+
foo\r
|
30
|
+
--#{m.boundary}\r
|
31
|
+
Content-Disposition: multipart/form-data; name="foo"\r
|
32
|
+
\r
|
33
|
+
bar\r
|
34
|
+
--#{m.boundary}--\r
|
35
|
+
EOS
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should form properly seperated multipart data" do
|
39
|
+
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
40
|
+
m = RestClient::Payload::Multipart.new({:foo => f})
|
41
|
+
m.to_s.should == <<-EOS
|
42
|
+
--#{m.boundary}\r
|
43
|
+
Content-Disposition: multipart/form-data; name="foo"; filename="./spec/master_shake.jpg"\r
|
44
|
+
Content-Type: image/jpeg\r
|
45
|
+
\r
|
46
|
+
#{IO.read(f.path)}\r
|
47
|
+
--#{m.boundary}--\r
|
48
|
+
EOS
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "Payload generation" do
|
53
|
+
it "should recognize standard urlencoded params" do
|
54
|
+
RestClient::Payload.generate({"foo" => 'bar'}).should be_kind_of(RestClient::Payload::UrlEncoded)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should recognize multipart params" do
|
58
|
+
f = File.new(File.dirname(__FILE__) + "/master_shake.jpg")
|
59
|
+
|
60
|
+
RestClient::Payload.generate({"foo" => f}).should be_kind_of(RestClient::Payload::Multipart)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should be multipart if forced" do
|
64
|
+
RestClient::Payload.generate({"foo" => "bar", :multipart => true}).should be_kind_of(RestClient::Payload::Multipart)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return data if no of the above" do
|
68
|
+
RestClient::Payload.generate("data").should be_kind_of(RestClient::Payload::Base)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe RestClient::Exception do
|
4
|
+
it "sets the exception message to ErrorMessage" do
|
5
|
+
RestClient::ResourceNotFound.new.message.should == 'Resource not found'
|
6
|
+
end
|
7
|
+
|
8
|
+
it "contains exceptions in RestClient" do
|
9
|
+
RestClient::Unauthorized.new.should be_a_kind_of(RestClient::Exception)
|
10
|
+
RestClient::ServerBrokeConnection.new.should be_a_kind_of(RestClient::Exception)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe RestClient::RequestFailed do
|
15
|
+
it "stores the http response on the exception" do
|
16
|
+
begin
|
17
|
+
raise RestClient::RequestFailed, :response
|
18
|
+
rescue RestClient::RequestFailed => e
|
19
|
+
e.response.should == :response
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "http_code convenience method for fetching the code as an integer" do
|
24
|
+
RestClient::RequestFailed.new(mock('res', :code => '502')).http_code.should == 502
|
25
|
+
end
|
26
|
+
|
27
|
+
it "shows the status code in the message" do
|
28
|
+
RestClient::RequestFailed.new(mock('res', :code => '502')).to_s.should match(/502/)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "backwards compatibility" do
|
33
|
+
it "alias RestClient::Request::Redirect to RestClient::Redirect" do
|
34
|
+
RestClient::Request::Redirect.should == RestClient::Redirect
|
35
|
+
end
|
36
|
+
|
37
|
+
it "alias RestClient::Request::Unauthorized to RestClient::Unauthorized" do
|
38
|
+
RestClient::Request::Unauthorized.should == RestClient::Unauthorized
|
39
|
+
end
|
40
|
+
|
41
|
+
it "alias RestClient::Request::RequestFailed to RestClient::RequestFailed" do
|
42
|
+
RestClient::Request::RequestFailed.should == RestClient::RequestFailed
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
describe RestClient::Resource do
|
4
|
+
before do
|
5
|
+
@resource = RestClient::Resource.new('http://some/resource', 'jane', 'mypass')
|
6
|
+
end
|
7
|
+
|
8
|
+
it "GET" do
|
9
|
+
RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {}, :user => 'jane', :password => 'mypass')
|
10
|
+
@resource.get
|
11
|
+
end
|
12
|
+
|
13
|
+
it "POST" do
|
14
|
+
RestClient::Request.should_receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'abc', :headers => { :content_type => 'image/jpg' }, :user => 'jane', :password => 'mypass')
|
15
|
+
@resource.post 'abc', :content_type => 'image/jpg'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "PUT" do
|
19
|
+
RestClient::Request.should_receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'abc', :headers => { :content_type => 'image/jpg' }, :user => 'jane', :password => 'mypass')
|
20
|
+
@resource.put 'abc', :content_type => 'image/jpg'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "DELETE" do
|
24
|
+
RestClient::Request.should_receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => {}, :user => 'jane', :password => 'mypass')
|
25
|
+
@resource.delete
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can instantiate with no user/password" do
|
29
|
+
@resource = RestClient::Resource.new('http://some/resource')
|
30
|
+
end
|
31
|
+
|
32
|
+
it "concatinates urls, inserting a slash when it needs one" do
|
33
|
+
@resource.concat_urls('http://example.com', 'resource').should == 'http://example.com/resource'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "concatinates urls, using no slash if the first url ends with a slash" do
|
37
|
+
@resource.concat_urls('http://example.com/', 'resource').should == 'http://example.com/resource'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "concatinates urls, using no slash if the second url starts with a slash" do
|
41
|
+
@resource.concat_urls('http://example.com', '/resource').should == 'http://example.com/resource'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "concatinates even non-string urls, :posts + 1 => 'posts/1'" do
|
45
|
+
@resource.concat_urls(:posts, 1).should == 'posts/1'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "offers subresources via []" do
|
49
|
+
parent = RestClient::Resource.new('http://example.com')
|
50
|
+
parent['posts'].url.should == 'http://example.com/posts'
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
|
+
|
3
|
+
def generate_payload(v)
|
4
|
+
RestClient::Payload::Base.new(v)
|
5
|
+
end
|
6
|
+
|
7
|
+
describe RestClient do
|
8
|
+
context "public API" do
|
9
|
+
it "GET" do
|
10
|
+
RestClient::Request.should_receive(:execute).with(:method => :get, :url => 'http://some/resource', :headers => {})
|
11
|
+
RestClient.get('http://some/resource')
|
12
|
+
end
|
13
|
+
|
14
|
+
it "POST" do
|
15
|
+
RestClient::Request.should_receive(:execute).with(:method => :post, :url => 'http://some/resource', :payload => 'payload', :headers => {})
|
16
|
+
RestClient.post('http://some/resource', 'payload')
|
17
|
+
end
|
18
|
+
|
19
|
+
it "PUT" do
|
20
|
+
RestClient::Request.should_receive(:execute).with(:method => :put, :url => 'http://some/resource', :payload => 'payload', :headers => {})
|
21
|
+
RestClient.put('http://some/resource', 'payload')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "DELETE" do
|
25
|
+
RestClient::Request.should_receive(:execute).with(:method => :delete, :url => 'http://some/resource', :headers => {})
|
26
|
+
RestClient.delete('http://some/resource')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context RestClient::Request do
|
31
|
+
before do
|
32
|
+
@request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
|
33
|
+
|
34
|
+
@uri = mock("uri")
|
35
|
+
@uri.stub!(:request_uri).and_return('/resource')
|
36
|
+
@uri.stub!(:host).and_return('some')
|
37
|
+
@uri.stub!(:port).and_return(80)
|
38
|
+
|
39
|
+
@net = mock("net::http base")
|
40
|
+
@http = mock("net::http connection")
|
41
|
+
Net::HTTP.stub!(:new).and_return(@net)
|
42
|
+
@net.stub!(:start).and_yield(@http)
|
43
|
+
@net.stub!(:use_ssl=)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "requests xml mimetype" do
|
47
|
+
@request.default_headers[:accept].should == 'application/xml'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "processes a successful result" do
|
51
|
+
res = mock("result")
|
52
|
+
res.stub!(:code).and_return("200")
|
53
|
+
res.stub!(:body).and_return('body')
|
54
|
+
@request.process_result(res).should == 'body'
|
55
|
+
end
|
56
|
+
|
57
|
+
it "parses a url into a URI object" do
|
58
|
+
URI.should_receive(:parse).with('http://example.com/resource')
|
59
|
+
@request.parse_url('http://example.com/resource')
|
60
|
+
end
|
61
|
+
|
62
|
+
it "adds http:// to the front of resources specified in the syntax example.com/resource" do
|
63
|
+
URI.should_receive(:parse).with('http://example.com/resource')
|
64
|
+
@request.parse_url('example.com/resource')
|
65
|
+
end
|
66
|
+
|
67
|
+
it "extracts the username and password when parsing http://user:password@example.com/" do
|
68
|
+
URI.stub!(:parse).and_return(mock('uri', :user => 'joe', :password => 'pass1'))
|
69
|
+
@request.parse_url_with_auth('http://joe:pass1@example.com/resource')
|
70
|
+
@request.user.should == 'joe'
|
71
|
+
@request.password.should == 'pass1'
|
72
|
+
end
|
73
|
+
|
74
|
+
it "doesn't overwrite user and password (which may have already been set by the Resource constructor) if there is no user/password in the url" do
|
75
|
+
URI.stub!(:parse).and_return(mock('uri', :user => nil, :password => nil))
|
76
|
+
@request = RestClient::Request.new(:method => 'get', :url => 'example.com', :user => 'beth', :password => 'pass2')
|
77
|
+
@request.parse_url_with_auth('http://example.com/resource')
|
78
|
+
@request.user.should == 'beth'
|
79
|
+
@request.password.should == 'pass2'
|
80
|
+
end
|
81
|
+
|
82
|
+
it "determines the Net::HTTP class to instantiate by the method name" do
|
83
|
+
@request.net_http_class(:put).should == Net::HTTP::Put
|
84
|
+
end
|
85
|
+
|
86
|
+
it "merges user headers with the default headers" do
|
87
|
+
@request.should_receive(:default_headers).and_return({ '1' => '2' })
|
88
|
+
@request.make_headers('3' => '4').should == { '1' => '2', '3' => '4' }
|
89
|
+
end
|
90
|
+
|
91
|
+
it "prefers the user header when the same header exists in the defaults" do
|
92
|
+
@request.should_receive(:default_headers).and_return({ '1' => '2' })
|
93
|
+
@request.make_headers('1' => '3').should == { '1' => '3' }
|
94
|
+
end
|
95
|
+
|
96
|
+
it "converts header symbols from :content_type to 'Content-type'" do
|
97
|
+
@request.should_receive(:default_headers).and_return({})
|
98
|
+
@request.make_headers(:content_type => 'abc').should == { 'Content-type' => 'abc' }
|
99
|
+
end
|
100
|
+
|
101
|
+
it "executes by constructing the Net::HTTP object, headers, and payload and calling transmit" do
|
102
|
+
@request.should_receive(:parse_url_with_auth).with('http://some/resource').and_return(@uri)
|
103
|
+
klass = mock("net:http class")
|
104
|
+
@request.should_receive(:net_http_class).with(:put).and_return(klass)
|
105
|
+
klass.should_receive(:new).and_return('result')
|
106
|
+
@request.should_receive(:transmit).with(@uri, 'result', be_kind_of(RestClient::Payload::Base))
|
107
|
+
@request.execute_inner
|
108
|
+
end
|
109
|
+
|
110
|
+
it "transmits the request with Net::HTTP" do
|
111
|
+
@http.should_receive(:request).with('req', be_kind_of(RestClient::Payload::Base))
|
112
|
+
@request.should_receive(:process_result)
|
113
|
+
@request.transmit(@uri, 'req', generate_payload('payload'))
|
114
|
+
end
|
115
|
+
|
116
|
+
it "uses SSL when the URI refers to a https address" do
|
117
|
+
@uri.stub!(:is_a?).with(URI::HTTPS).and_return(true)
|
118
|
+
@net.should_receive(:use_ssl=).with(true)
|
119
|
+
@http.stub!(:request)
|
120
|
+
@request.stub!(:process_result)
|
121
|
+
@request.transmit(@uri, 'req', generate_payload('payload'))
|
122
|
+
end
|
123
|
+
|
124
|
+
it "passes non-hash payloads straight through" do
|
125
|
+
@request.process_payload("x").should == "x"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "converts a hash payload to urlencoded data" do
|
129
|
+
@request.process_payload(:a => 'b c+d').should == "a=b%20c%2Bd"
|
130
|
+
end
|
131
|
+
|
132
|
+
it "accepts nested hashes in payload" do
|
133
|
+
payload = @request.process_payload(:user => { :name => 'joe', :location => { :country => 'USA', :state => 'CA' }})
|
134
|
+
payload.should include('user[name]=joe')
|
135
|
+
payload.should include('user[location][country]=USA')
|
136
|
+
payload.should include('user[location][state]=CA')
|
137
|
+
end
|
138
|
+
|
139
|
+
it "set urlencoded content_type header on hash payloads" do
|
140
|
+
@request.process_payload(:a => 1)
|
141
|
+
@request.headers[:content_type].should == 'application/x-www-form-urlencoded'
|
142
|
+
end
|
143
|
+
|
144
|
+
it "sets up the credentials prior to the request" do
|
145
|
+
@http.stub!(:request)
|
146
|
+
@request.stub!(:process_result)
|
147
|
+
|
148
|
+
@request.stub!(:user).and_return('joe')
|
149
|
+
@request.stub!(:password).and_return('mypass')
|
150
|
+
@request.should_receive(:setup_credentials).with('req')
|
151
|
+
|
152
|
+
@request.transmit(@uri, 'req', generate_payload(''))
|
153
|
+
end
|
154
|
+
|
155
|
+
it "does not attempt to send any credentials if user is nil" do
|
156
|
+
@request.stub!(:user).and_return(nil)
|
157
|
+
req = mock("request")
|
158
|
+
req.should_not_receive(:basic_auth)
|
159
|
+
@request.setup_credentials(req)
|
160
|
+
end
|
161
|
+
|
162
|
+
it "setup credentials when there's a user" do
|
163
|
+
@request.stub!(:user).and_return('joe')
|
164
|
+
@request.stub!(:password).and_return('mypass')
|
165
|
+
req = mock("request")
|
166
|
+
req.should_receive(:basic_auth).with('joe', 'mypass')
|
167
|
+
@request.setup_credentials(req)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "catches EOFError and shows the more informative ServerBrokeConnection" do
|
171
|
+
@http.stub!(:request).and_raise(EOFError)
|
172
|
+
lambda { @request.transmit(@uri, 'req', generate_payload('')) }.
|
173
|
+
should raise_error(RestClient::ServerBrokeConnection)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "execute calls execute_inner" do
|
177
|
+
@request.should_receive(:execute_inner)
|
178
|
+
@request.execute
|
179
|
+
end
|
180
|
+
|
181
|
+
it "class method execute wraps constructor" do
|
182
|
+
req = mock("rest request")
|
183
|
+
RestClient::Request.should_receive(:new).with(1 => 2).and_return(req)
|
184
|
+
req.should_receive(:execute)
|
185
|
+
RestClient::Request.execute(1 => 2)
|
186
|
+
end
|
187
|
+
|
188
|
+
it "raises a Redirect with the new location when the response is in the 30x range" do
|
189
|
+
res = mock('response', :code => '301', :header => { 'Location' => 'http://new/resource' })
|
190
|
+
lambda { @request.process_result(res) }.should raise_error(RestClient::Redirect) { |e| e.url.should == 'http://new/resource'}
|
191
|
+
end
|
192
|
+
|
193
|
+
it "handles redirects with relative paths" do
|
194
|
+
res = mock('response', :code => '301', :header => { 'Location' => 'index' })
|
195
|
+
lambda { @request.process_result(res) }.should raise_error(RestClient::Redirect) { |e| e.url.should == 'http://some/index' }
|
196
|
+
end
|
197
|
+
|
198
|
+
it "handles redirects with absolute paths" do
|
199
|
+
@request.instance_variable_set('@url', 'http://some/place/else')
|
200
|
+
res = mock('response', :code => '301', :header => { 'Location' => '/index' })
|
201
|
+
lambda { @request.process_result(res) }.should raise_error(RestClient::Redirect) { |e| e.url.should == 'http://some/index' }
|
202
|
+
end
|
203
|
+
|
204
|
+
it "raises Unauthorized when the response is 401" do
|
205
|
+
res = mock('response', :code => '401')
|
206
|
+
lambda { @request.process_result(res) }.should raise_error(RestClient::Unauthorized)
|
207
|
+
end
|
208
|
+
|
209
|
+
it "raises ResourceNotFound when the response is 404" do
|
210
|
+
res = mock('response', :code => '404')
|
211
|
+
lambda { @request.process_result(res) }.should raise_error(RestClient::ResourceNotFound)
|
212
|
+
end
|
213
|
+
|
214
|
+
it "raises RequestFailed otherwise" do
|
215
|
+
res = mock('response', :code => '500')
|
216
|
+
lambda { @request.process_result(res) }.should raise_error(RestClient::RequestFailed)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|