rest-client-maestro 1.7.2.maestro
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 +8 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +8 -0
- data/AUTHORS +69 -0
- data/Gemfile +7 -0
- data/README.rdoc +322 -0
- data/Rakefile +49 -0
- data/bin/restclient +93 -0
- data/history.md +134 -0
- data/lib/rest-client.rb +2 -0
- data/lib/rest_client.rb +2 -0
- data/lib/restclient/abstract_response.rb +106 -0
- data/lib/restclient/exceptions.rb +198 -0
- data/lib/restclient/net_http_ext.rb +55 -0
- data/lib/restclient/payload.rb +242 -0
- data/lib/restclient/raw_response.rb +34 -0
- data/lib/restclient/request.rb +346 -0
- data/lib/restclient/resource.rb +169 -0
- data/lib/restclient/response.rb +26 -0
- data/lib/restclient.rb +174 -0
- data/rest-client-maestro.gemspec +23 -0
- data/spec/integration/capath_equifax/578d5c04.0 +19 -0
- data/spec/integration/capath_equifax/594f1775.0 +19 -0
- data/spec/integration/capath_equifax/README +8 -0
- data/spec/integration/capath_equifax/equifax.crt +19 -0
- data/spec/integration/capath_verisign/415660c1.0 +14 -0
- data/spec/integration/capath_verisign/7651b327.0 +14 -0
- data/spec/integration/capath_verisign/README +8 -0
- data/spec/integration/capath_verisign/verisign.crt +14 -0
- data/spec/integration/certs/equifax.crt +19 -0
- data/spec/integration/certs/verisign.crt +14 -0
- data/spec/integration/integration_spec.rb +35 -0
- data/spec/integration/request_spec.rb +63 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/unit/abstract_response_spec.rb +85 -0
- data/spec/unit/exceptions_spec.rb +95 -0
- data/spec/unit/master_shake.jpg +0 -0
- data/spec/unit/payload_spec.rb +245 -0
- data/spec/unit/raw_response_spec.rb +17 -0
- data/spec/unit/request2_spec.rb +32 -0
- data/spec/unit/request_spec.rb +621 -0
- data/spec/unit/resource_spec.rb +133 -0
- data/spec/unit/response_spec.rb +166 -0
- data/spec/unit/restclient_spec.rb +73 -0
- metadata +220 -0
@@ -0,0 +1,169 @@
|
|
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 => 'user', :password => 'password')
|
13
|
+
# resource.delete
|
14
|
+
#
|
15
|
+
# With a timeout (seconds):
|
16
|
+
#
|
17
|
+
# RestClient::Resource.new('http://slow', :timeout => 10)
|
18
|
+
#
|
19
|
+
# With an open timeout (seconds):
|
20
|
+
#
|
21
|
+
# RestClient::Resource.new('http://behindfirewall', :open_timeout => 10)
|
22
|
+
#
|
23
|
+
# You can also use resources to share common headers. For headers keys,
|
24
|
+
# symbols are converted to strings. Example:
|
25
|
+
#
|
26
|
+
# resource = RestClient::Resource.new('http://some/resource', :headers => { :client_version => 1 })
|
27
|
+
#
|
28
|
+
# This header will be transported as X-Client-Version (notice the X prefix,
|
29
|
+
# capitalization and hyphens)
|
30
|
+
#
|
31
|
+
# Use the [] syntax to allocate subresources:
|
32
|
+
#
|
33
|
+
# site = RestClient::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
|
34
|
+
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
35
|
+
#
|
36
|
+
class Resource
|
37
|
+
attr_reader :url, :options, :block
|
38
|
+
|
39
|
+
def initialize(url, options={}, backwards_compatibility=nil, &block)
|
40
|
+
@url = url
|
41
|
+
@block = block
|
42
|
+
if options.class == Hash
|
43
|
+
@options = options
|
44
|
+
else # compatibility with previous versions
|
45
|
+
@options = { :user => options, :password => backwards_compatibility }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def get(additional_headers={}, &block)
|
50
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
51
|
+
Request.execute(options.merge(
|
52
|
+
:method => :get,
|
53
|
+
:url => url,
|
54
|
+
:headers => headers), &(block || @block))
|
55
|
+
end
|
56
|
+
|
57
|
+
def head(additional_headers={}, &block)
|
58
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
59
|
+
Request.execute(options.merge(
|
60
|
+
:method => :head,
|
61
|
+
:url => url,
|
62
|
+
:headers => headers), &(block || @block))
|
63
|
+
end
|
64
|
+
|
65
|
+
def post(payload, additional_headers={}, &block)
|
66
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
67
|
+
Request.execute(options.merge(
|
68
|
+
:method => :post,
|
69
|
+
:url => url,
|
70
|
+
:payload => payload,
|
71
|
+
:headers => headers), &(block || @block))
|
72
|
+
end
|
73
|
+
|
74
|
+
def put(payload, additional_headers={}, &block)
|
75
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
76
|
+
Request.execute(options.merge(
|
77
|
+
:method => :put,
|
78
|
+
:url => url,
|
79
|
+
:payload => payload,
|
80
|
+
:headers => headers), &(block || @block))
|
81
|
+
end
|
82
|
+
|
83
|
+
def patch(payload, additional_headers={}, &block)
|
84
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
85
|
+
Request.execute(options.merge(
|
86
|
+
:method => :patch,
|
87
|
+
:url => url,
|
88
|
+
:payload => payload,
|
89
|
+
:headers => headers), &(block || @block))
|
90
|
+
end
|
91
|
+
|
92
|
+
def delete(additional_headers={}, &block)
|
93
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
94
|
+
Request.execute(options.merge(
|
95
|
+
:method => :delete,
|
96
|
+
:url => url,
|
97
|
+
:headers => headers), &(block || @block))
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_s
|
101
|
+
url
|
102
|
+
end
|
103
|
+
|
104
|
+
def user
|
105
|
+
options[:user]
|
106
|
+
end
|
107
|
+
|
108
|
+
def password
|
109
|
+
options[:password]
|
110
|
+
end
|
111
|
+
|
112
|
+
def headers
|
113
|
+
options[:headers] || {}
|
114
|
+
end
|
115
|
+
|
116
|
+
def timeout
|
117
|
+
options[:timeout]
|
118
|
+
end
|
119
|
+
|
120
|
+
def open_timeout
|
121
|
+
options[:open_timeout]
|
122
|
+
end
|
123
|
+
|
124
|
+
# Construct a subresource, preserving authentication.
|
125
|
+
#
|
126
|
+
# Example:
|
127
|
+
#
|
128
|
+
# site = RestClient::Resource.new('http://example.com', 'adam', 'mypasswd')
|
129
|
+
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
130
|
+
#
|
131
|
+
# This is especially useful if you wish to define your site in one place and
|
132
|
+
# call it in multiple locations:
|
133
|
+
#
|
134
|
+
# def orders
|
135
|
+
# RestClient::Resource.new('http://example.com/orders', 'admin', 'mypasswd')
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
# orders.get # GET http://example.com/orders
|
139
|
+
# orders['1'].get # GET http://example.com/orders/1
|
140
|
+
# orders['1/items'].delete # DELETE http://example.com/orders/1/items
|
141
|
+
#
|
142
|
+
# Nest resources as far as you want:
|
143
|
+
#
|
144
|
+
# site = RestClient::Resource.new('http://example.com')
|
145
|
+
# posts = site['posts']
|
146
|
+
# first_post = posts['1']
|
147
|
+
# comments = first_post['comments']
|
148
|
+
# comments.post 'Hello', :content_type => 'text/plain'
|
149
|
+
#
|
150
|
+
def [](suburl, &new_block)
|
151
|
+
case
|
152
|
+
when block_given? then self.class.new(concat_urls(url, suburl), options, &new_block)
|
153
|
+
when block then self.class.new(concat_urls(url, suburl), options, &block)
|
154
|
+
else
|
155
|
+
self.class.new(concat_urls(url, suburl), options)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def concat_urls(url, suburl) # :nodoc:
|
160
|
+
url = url.to_s
|
161
|
+
suburl = suburl.to_s
|
162
|
+
if url.slice(-1, 1) == '/' or suburl.slice(0, 1) == '/'
|
163
|
+
url + suburl
|
164
|
+
else
|
165
|
+
"#{url}/#{suburl}"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module RestClient
|
2
|
+
|
3
|
+
# A Response from RestClient, you can access the response body, the code or the headers.
|
4
|
+
#
|
5
|
+
module Response
|
6
|
+
|
7
|
+
include AbstractResponse
|
8
|
+
|
9
|
+
attr_accessor :args, :net_http_res
|
10
|
+
|
11
|
+
attr_writer :body
|
12
|
+
|
13
|
+
def body
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def Response.create body, net_http_res, args
|
18
|
+
result = body || ''
|
19
|
+
result.extend Response
|
20
|
+
result.net_http_res = net_http_res
|
21
|
+
result.args = args
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
data/lib/restclient.rb
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'zlib'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'net/https'
|
7
|
+
rescue LoadError => e
|
8
|
+
raise e unless RUBY_PLATFORM =~ /linux/
|
9
|
+
raise LoadError, "no such file to load -- net/https. Try running apt-get install libopenssl-ruby"
|
10
|
+
end
|
11
|
+
|
12
|
+
require File.dirname(__FILE__) + '/restclient/exceptions'
|
13
|
+
require File.dirname(__FILE__) + '/restclient/request'
|
14
|
+
require File.dirname(__FILE__) + '/restclient/abstract_response'
|
15
|
+
require File.dirname(__FILE__) + '/restclient/response'
|
16
|
+
require File.dirname(__FILE__) + '/restclient/raw_response'
|
17
|
+
require File.dirname(__FILE__) + '/restclient/resource'
|
18
|
+
require File.dirname(__FILE__) + '/restclient/payload'
|
19
|
+
require File.dirname(__FILE__) + '/restclient/net_http_ext'
|
20
|
+
|
21
|
+
# This module's static methods are the entry point for using the REST client.
|
22
|
+
#
|
23
|
+
# # GET
|
24
|
+
# xml = RestClient.get 'http://example.com/resource'
|
25
|
+
# jpg = RestClient.get 'http://example.com/resource', :accept => 'image/jpg'
|
26
|
+
#
|
27
|
+
# # authentication and SSL
|
28
|
+
# RestClient.get 'https://user:password@example.com/private/resource'
|
29
|
+
#
|
30
|
+
# # POST or PUT with a hash sends parameters as a urlencoded form body
|
31
|
+
# RestClient.post 'http://example.com/resource', :param1 => 'one'
|
32
|
+
#
|
33
|
+
# # nest hash parameters
|
34
|
+
# RestClient.post 'http://example.com/resource', :nested => { :param1 => 'one' }
|
35
|
+
#
|
36
|
+
# # POST and PUT with raw payloads
|
37
|
+
# RestClient.post 'http://example.com/resource', 'the post body', :content_type => 'text/plain'
|
38
|
+
# RestClient.post 'http://example.com/resource.xml', xml_doc
|
39
|
+
# RestClient.put 'http://example.com/resource.pdf', File.read('my.pdf'), :content_type => 'application/pdf'
|
40
|
+
#
|
41
|
+
# # DELETE
|
42
|
+
# RestClient.delete 'http://example.com/resource'
|
43
|
+
#
|
44
|
+
# # retreive the response http code and headers
|
45
|
+
# res = RestClient.get 'http://example.com/some.jpg'
|
46
|
+
# res.code # => 200
|
47
|
+
# res.headers[:content_type] # => 'image/jpg'
|
48
|
+
#
|
49
|
+
# # HEAD
|
50
|
+
# RestClient.head('http://example.com').headers
|
51
|
+
#
|
52
|
+
# To use with a proxy, just set RestClient.proxy to the proper http proxy:
|
53
|
+
#
|
54
|
+
# RestClient.proxy = "http://proxy.example.com/"
|
55
|
+
#
|
56
|
+
# Or inherit the proxy from the environment:
|
57
|
+
#
|
58
|
+
# RestClient.proxy = ENV['http_proxy']
|
59
|
+
#
|
60
|
+
# For live tests of RestClient, try using http://rest-test.heroku.com, which echoes back information about the rest call:
|
61
|
+
#
|
62
|
+
# >> RestClient.put 'http://rest-test.heroku.com/resource', :foo => 'baz'
|
63
|
+
# => "PUT http://rest-test.heroku.com/resource with a 7 byte payload, content type application/x-www-form-urlencoded {\"foo\"=>\"baz\"}"
|
64
|
+
#
|
65
|
+
module RestClient
|
66
|
+
|
67
|
+
def self.get(url, headers={}, &block)
|
68
|
+
Request.execute(:method => :get, :url => url, :headers => headers, &block)
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.post(url, payload, headers={}, &block)
|
72
|
+
Request.execute(:method => :post, :url => url, :payload => payload, :headers => headers, &block)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.patch(url, payload, headers={}, &block)
|
76
|
+
Request.execute(:method => :patch, :url => url, :payload => payload, :headers => headers, &block)
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.put(url, payload, headers={}, &block)
|
80
|
+
Request.execute(:method => :put, :url => url, :payload => payload, :headers => headers, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.delete(url, headers={}, &block)
|
84
|
+
Request.execute(:method => :delete, :url => url, :headers => headers, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.head(url, headers={}, &block)
|
88
|
+
Request.execute(:method => :head, :url => url, :headers => headers, &block)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.options(url, headers={}, &block)
|
92
|
+
Request.execute(:method => :options, :url => url, :headers => headers, &block)
|
93
|
+
end
|
94
|
+
|
95
|
+
class << self
|
96
|
+
attr_accessor :proxy
|
97
|
+
end
|
98
|
+
|
99
|
+
# Setup the log for RestClient calls.
|
100
|
+
# Value should be a logger but can can be stdout, stderr, or a filename.
|
101
|
+
# You can also configure logging by the environment variable RESTCLIENT_LOG.
|
102
|
+
def self.log= log
|
103
|
+
@@log = create_log log
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.version
|
107
|
+
version_path = File.dirname(__FILE__) + "/../VERSION"
|
108
|
+
return File.read(version_path).chomp if File.file?(version_path)
|
109
|
+
"0.0.0"
|
110
|
+
end
|
111
|
+
|
112
|
+
# Create a log that respond to << like a logger
|
113
|
+
# param can be 'stdout', 'stderr', a string (then we will log to that file) or a logger (then we return it)
|
114
|
+
def self.create_log param
|
115
|
+
if param
|
116
|
+
if param.is_a? String
|
117
|
+
if param == 'stdout'
|
118
|
+
stdout_logger = Class.new do
|
119
|
+
def << obj
|
120
|
+
STDOUT.puts obj
|
121
|
+
end
|
122
|
+
end
|
123
|
+
stdout_logger.new
|
124
|
+
elsif param == 'stderr'
|
125
|
+
stderr_logger = Class.new do
|
126
|
+
def << obj
|
127
|
+
STDERR.puts obj
|
128
|
+
end
|
129
|
+
end
|
130
|
+
stderr_logger.new
|
131
|
+
else
|
132
|
+
file_logger = Class.new do
|
133
|
+
attr_writer :target_file
|
134
|
+
|
135
|
+
def << obj
|
136
|
+
File.open(@target_file, 'a') { |f| f.puts obj }
|
137
|
+
end
|
138
|
+
end
|
139
|
+
logger = file_logger.new
|
140
|
+
logger.target_file = param
|
141
|
+
logger
|
142
|
+
end
|
143
|
+
else
|
144
|
+
param
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
@@env_log = create_log ENV['RESTCLIENT_LOG']
|
150
|
+
|
151
|
+
@@log = nil
|
152
|
+
|
153
|
+
def self.log # :nodoc:
|
154
|
+
@@env_log || @@log
|
155
|
+
end
|
156
|
+
|
157
|
+
@@before_execution_procs = []
|
158
|
+
|
159
|
+
# Add a Proc to be called before each request in executed.
|
160
|
+
# The proc parameters will be the http request and the request params.
|
161
|
+
def self.add_before_execution_proc &proc
|
162
|
+
@@before_execution_procs << proc
|
163
|
+
end
|
164
|
+
|
165
|
+
# Reset the procs to be called before each request is executed.
|
166
|
+
def self.reset_before_execution_procs
|
167
|
+
@@before_execution_procs = []
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.before_execution_procs # :nodoc:
|
171
|
+
@@before_execution_procs
|
172
|
+
end
|
173
|
+
|
174
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'rest-client-maestro'
|
5
|
+
s.version = '1.7.2.maestro'
|
6
|
+
s.authors = ['REST Client Team']
|
7
|
+
s.description = 'A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete.'
|
8
|
+
s.license = 'MIT'
|
9
|
+
s.email = 'rest.client@librelist.com'
|
10
|
+
s.executables = ['restclient']
|
11
|
+
s.extra_rdoc_files = ["README.rdoc", "history.md"]
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
14
|
+
s.homepage = 'http://github.com/maestrodev/rest-client'
|
15
|
+
s.summary = 'Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions.'
|
16
|
+
|
17
|
+
s.add_runtime_dependency(%q<mime-types>, [">= 1.16", "< 2.0"])
|
18
|
+
s.add_development_dependency(%q<webmock>, ["~> 1.4"])
|
19
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.4"])
|
20
|
+
s.add_dependency(%q<netrc>, ["~> 0.7.7"])
|
21
|
+
s.add_dependency(%q<rdoc>, [">= 2.4.2"])
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
|
3
|
+
UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
|
4
|
+
dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
|
5
|
+
MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
|
6
|
+
dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
|
7
|
+
AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
|
8
|
+
BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
|
9
|
+
cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
|
10
|
+
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
|
11
|
+
MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
|
12
|
+
aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
|
13
|
+
ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
|
14
|
+
IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
|
15
|
+
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
|
16
|
+
A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
|
17
|
+
7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
|
18
|
+
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
|
19
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,19 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
|
3
|
+
UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
|
4
|
+
dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
|
5
|
+
MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
|
6
|
+
dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
|
7
|
+
AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
|
8
|
+
BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
|
9
|
+
cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
|
10
|
+
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
|
11
|
+
MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
|
12
|
+
aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
|
13
|
+
ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
|
14
|
+
IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
|
15
|
+
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
|
16
|
+
A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
|
17
|
+
7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
|
18
|
+
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
|
19
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,8 @@
|
|
1
|
+
The CA path symlinks can be created by c_rehash(1ssl).
|
2
|
+
|
3
|
+
But in order for the tests to work on Windows, they have to be regular files.
|
4
|
+
You can turn them all into regular files by running this on a GNU system:
|
5
|
+
|
6
|
+
for file in $(find . -type l); do
|
7
|
+
cp -iv --remove-destination $(readlink -e $file) $file
|
8
|
+
done
|
@@ -0,0 +1,19 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
|
3
|
+
UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
|
4
|
+
dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
|
5
|
+
MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
|
6
|
+
dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
|
7
|
+
AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
|
8
|
+
BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
|
9
|
+
cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
|
10
|
+
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
|
11
|
+
MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
|
12
|
+
aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
|
13
|
+
ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
|
14
|
+
IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
|
15
|
+
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
|
16
|
+
A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
|
17
|
+
7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
|
18
|
+
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
|
19
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
|
3
|
+
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
4
|
+
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
|
5
|
+
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
|
6
|
+
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
|
7
|
+
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
|
8
|
+
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
|
9
|
+
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
|
10
|
+
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
|
11
|
+
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
|
12
|
+
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
|
13
|
+
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
|
14
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
|
3
|
+
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
4
|
+
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
|
5
|
+
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
|
6
|
+
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
|
7
|
+
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
|
8
|
+
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
|
9
|
+
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
|
10
|
+
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
|
11
|
+
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
|
12
|
+
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
|
13
|
+
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
|
14
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,8 @@
|
|
1
|
+
The CA path symlinks can be created by c_rehash(1ssl).
|
2
|
+
|
3
|
+
But in order for the tests to work on Windows, they have to be regular files.
|
4
|
+
You can turn them all into regular files by running this on a GNU system:
|
5
|
+
|
6
|
+
for file in $(find . -type l); do
|
7
|
+
cp -iv --remove-destination $(readlink -e $file) $file
|
8
|
+
done
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
|
3
|
+
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
4
|
+
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
|
5
|
+
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
|
6
|
+
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
|
7
|
+
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
|
8
|
+
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
|
9
|
+
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
|
10
|
+
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
|
11
|
+
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
|
12
|
+
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
|
13
|
+
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
|
14
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,19 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
|
3
|
+
UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
|
4
|
+
dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
|
5
|
+
MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
|
6
|
+
dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
|
7
|
+
AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
|
8
|
+
BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
|
9
|
+
cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
|
10
|
+
AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
|
11
|
+
MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
|
12
|
+
aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
|
13
|
+
ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
|
14
|
+
IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
|
15
|
+
MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
|
16
|
+
A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
|
17
|
+
7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
|
18
|
+
1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
|
19
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,14 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
|
3
|
+
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
4
|
+
cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
|
5
|
+
MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
|
6
|
+
BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
|
7
|
+
YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
|
8
|
+
ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
|
9
|
+
BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
|
10
|
+
I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
|
11
|
+
CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
|
12
|
+
lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
|
13
|
+
AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
|
14
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RestClient do
|
4
|
+
|
5
|
+
it "a simple request" do
|
6
|
+
body = 'abc'
|
7
|
+
stub_request(:get, "www.example.com").to_return(:body => body, :status => 200)
|
8
|
+
response = RestClient.get "www.example.com"
|
9
|
+
response.code.should eq 200
|
10
|
+
response.body.should eq body
|
11
|
+
end
|
12
|
+
|
13
|
+
it "a simple request with gzipped content" do
|
14
|
+
stub_request(:get, "www.example.com").with(:headers => { 'Accept-Encoding' => 'gzip, deflate' }).to_return(:body => "\037\213\b\b\006'\252H\000\003t\000\313T\317UH\257\312,HM\341\002\000G\242(\r\v\000\000\000", :status => 200, :headers => { 'Content-Encoding' => 'gzip' } )
|
15
|
+
response = RestClient.get "www.example.com"
|
16
|
+
response.code.should eq 200
|
17
|
+
response.body.should eq "i'm gziped\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "a 404" do
|
21
|
+
body = "Ho hai ! I'm not here !"
|
22
|
+
stub_request(:get, "www.example.com").to_return(:body => body, :status => 404)
|
23
|
+
begin
|
24
|
+
RestClient.get "www.example.com"
|
25
|
+
raise
|
26
|
+
rescue RestClient::ResourceNotFound => e
|
27
|
+
e.http_code.should eq 404
|
28
|
+
e.response.code.should eq 404
|
29
|
+
e.response.body.should eq body
|
30
|
+
e.http_body.should eq body
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RestClient::Request do
|
4
|
+
before(:all) do
|
5
|
+
WebMock.disable!
|
6
|
+
end
|
7
|
+
|
8
|
+
after(:all) do
|
9
|
+
WebMock.enable!
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "ssl verification" do
|
13
|
+
it "is successful with the correct ca_file" do
|
14
|
+
request = RestClient::Request.new(
|
15
|
+
:method => :get,
|
16
|
+
:url => 'https://www.mozilla.com',
|
17
|
+
:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
|
18
|
+
:ssl_ca_file => File.join(File.dirname(__FILE__), "certs", "equifax.crt")
|
19
|
+
)
|
20
|
+
expect { request.execute }.to_not raise_error
|
21
|
+
end
|
22
|
+
|
23
|
+
it "is successful with the correct ca_path" do
|
24
|
+
request = RestClient::Request.new(
|
25
|
+
:method => :get,
|
26
|
+
:url => 'https://www.mozilla.com',
|
27
|
+
:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
|
28
|
+
:ssl_ca_path => File.join(File.dirname(__FILE__), "capath_equifax")
|
29
|
+
)
|
30
|
+
expect { request.execute }.to_not raise_error
|
31
|
+
end
|
32
|
+
|
33
|
+
# I don' think this feature is useful anymore (under 1.9.3 at the very least).
|
34
|
+
#
|
35
|
+
# Exceptions in verify_callback are ignored; RestClient has to catch OpenSSL::SSL::SSLError
|
36
|
+
# and either re-throw it as is, or throw SSLCertificateNotVerified
|
37
|
+
# based on the contents of the message field of the original exception
|
38
|
+
#.
|
39
|
+
# The client has to handle OpenSSL::SSL::SSLError exceptions anyway,
|
40
|
+
# why make them handle both OpenSSL *AND* RestClient exceptions???
|
41
|
+
#
|
42
|
+
# also see https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl.c#L237
|
43
|
+
it "is unsuccessful with an incorrect ca_file" do
|
44
|
+
request = RestClient::Request.new(
|
45
|
+
:method => :get,
|
46
|
+
:url => 'https://www.mozilla.com',
|
47
|
+
:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
|
48
|
+
:ssl_ca_file => File.join(File.dirname(__FILE__), "certs", "verisign.crt")
|
49
|
+
)
|
50
|
+
expect { request.execute }.to raise_error(RestClient::SSLCertificateNotVerified)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "is unsuccessful with an incorrect ca_path" do
|
54
|
+
request = RestClient::Request.new(
|
55
|
+
:method => :get,
|
56
|
+
:url => 'https://www.mozilla.com',
|
57
|
+
:verify_ssl => OpenSSL::SSL::VERIFY_PEER,
|
58
|
+
:ssl_ca_path => File.join(File.dirname(__FILE__), "capath_verisign")
|
59
|
+
)
|
60
|
+
expect { request.execute }.to raise_error(RestClient::SSLCertificateNotVerified)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|