cfoundry 0.7.0.rc3 → 0.7.0.rc4
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/lib/cfoundry/baseclient.rb +2 -2
- data/lib/cfoundry/rest_client.rb +27 -9
- data/lib/cfoundry/v2/client.rb +4 -57
- data/lib/cfoundry/version.rb +1 -1
- data/spec/cfoundry/rest_client_spec.rb +100 -28
- metadata +3 -3
data/lib/cfoundry/baseclient.rb
CHANGED
@@ -12,8 +12,8 @@ module CFoundry
|
|
12
12
|
attr_reader :rest_client
|
13
13
|
|
14
14
|
def_delegators :rest_client, :target, :target=, :token,
|
15
|
-
:
|
16
|
-
:
|
15
|
+
:trace, :backtrace, :backtrace=, :log, :log=,
|
16
|
+
:http_proxy, :http_proxy=, :https_proxy, :https_proxy=
|
17
17
|
|
18
18
|
def initialize(target = "https://api.cloudfoundry.com", token = nil)
|
19
19
|
@rest_client = CFoundry::RestClient.new(target, token)
|
data/lib/cfoundry/rest_client.rb
CHANGED
@@ -6,6 +6,29 @@ require "fileutils"
|
|
6
6
|
|
7
7
|
module CFoundry
|
8
8
|
class RestClient
|
9
|
+
class HTTPFactory
|
10
|
+
def self.create(uri, http_proxy, https_proxy)
|
11
|
+
scheme = uri.scheme
|
12
|
+
proxy_to_use = (scheme == "http" ? http_proxy : https_proxy)
|
13
|
+
|
14
|
+
if proxy_to_use
|
15
|
+
proxy_uri = URI.parse(proxy_to_use)
|
16
|
+
proxy_user, proxy_pass = proxy_uri.userinfo.split(/:/) if proxy_uri.userinfo
|
17
|
+
http = Net::HTTP::Proxy(proxy_uri.host, proxy_uri.port, proxy_user, proxy_pass).
|
18
|
+
new(uri.host, uri.port)
|
19
|
+
else
|
20
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
21
|
+
end
|
22
|
+
|
23
|
+
if scheme == "https"
|
24
|
+
http.use_ssl = true
|
25
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
26
|
+
end
|
27
|
+
|
28
|
+
return http
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
9
32
|
include CFoundry::TraceHelpers
|
10
33
|
|
11
34
|
LOG_LENGTH = 10
|
@@ -24,7 +47,9 @@ module CFoundry
|
|
24
47
|
|
25
48
|
attr_reader :target
|
26
49
|
|
27
|
-
attr_accessor :trace, :backtrace, :log,
|
50
|
+
attr_accessor :trace, :backtrace, :log,
|
51
|
+
:request_id, :token, :target,
|
52
|
+
:http_proxy, :https_proxy
|
28
53
|
|
29
54
|
def initialize(target, token = nil)
|
30
55
|
@target = target
|
@@ -49,7 +74,6 @@ module CFoundry
|
|
49
74
|
|
50
75
|
headers["X-Request-Id"] = @request_id if @request_id
|
51
76
|
headers["Authorization"] = @token.auth_header if @token
|
52
|
-
headers["Proxy-User"] = @proxy if @proxy
|
53
77
|
|
54
78
|
if accept_type = mimetype(options[:accept])
|
55
79
|
headers["Accept"] = accept_type
|
@@ -118,17 +142,11 @@ module CFoundry
|
|
118
142
|
|
119
143
|
add_headers(request, headers)
|
120
144
|
|
121
|
-
|
122
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
145
|
+
http = HTTPFactory.create(uri, http_proxy, https_proxy)
|
123
146
|
|
124
147
|
# TODO remove this when staging returns streaming responses
|
125
148
|
http.read_timeout = 300
|
126
149
|
|
127
|
-
if uri.is_a?(URI::HTTPS)
|
128
|
-
http.use_ssl = true
|
129
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
130
|
-
end
|
131
|
-
|
132
150
|
before = Time.now
|
133
151
|
http.start do
|
134
152
|
response = http.request(request)
|
data/lib/cfoundry/v2/client.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.expand_path("../../concerns/login_helpers", __FILE__)
|
2
|
+
require "forwardable"
|
2
3
|
|
3
4
|
module CFoundry::V2
|
4
5
|
# The primary API entrypoint. Wraps a BaseClient to provide nicer return
|
@@ -6,6 +7,7 @@ module CFoundry::V2
|
|
6
7
|
# are the only two internal states.
|
7
8
|
class Client
|
8
9
|
include ClientMethods, CFoundry::LoginHelpers
|
10
|
+
extend Forwardable
|
9
11
|
|
10
12
|
# Internal BaseClient instance. Normally won't be touching this.
|
11
13
|
attr_reader :base
|
@@ -16,6 +18,8 @@ module CFoundry::V2
|
|
16
18
|
# [Space] Currently targeted space.
|
17
19
|
attr_accessor :current_space
|
18
20
|
|
21
|
+
def_delegators :@base, :target, :token, :token=, :http_proxy, :http_proxy=,
|
22
|
+
:https_proxy, :https_proxy=, :trace, :trace=, :log, :log=, :info
|
19
23
|
|
20
24
|
# Create a new Client for interfacing with the given target.
|
21
25
|
#
|
@@ -28,58 +32,6 @@ module CFoundry::V2
|
|
28
32
|
2
|
29
33
|
end
|
30
34
|
|
31
|
-
# The current target URL of the client.
|
32
|
-
def target
|
33
|
-
@base.target
|
34
|
-
end
|
35
|
-
|
36
|
-
# Current authentication token.
|
37
|
-
def token
|
38
|
-
@base.token
|
39
|
-
end
|
40
|
-
|
41
|
-
# Set the authentication token.
|
42
|
-
def token=(token)
|
43
|
-
@base.token = token
|
44
|
-
end
|
45
|
-
|
46
|
-
# Current proxy user. Usually nil.
|
47
|
-
def proxy
|
48
|
-
@base.proxy
|
49
|
-
end
|
50
|
-
|
51
|
-
# Set the proxy user for the client. Must be authorized as an
|
52
|
-
# administrator for this to have any effect.
|
53
|
-
def proxy=(email)
|
54
|
-
@base.proxy = email
|
55
|
-
end
|
56
|
-
|
57
|
-
# Is the client tracing API requests?
|
58
|
-
def trace
|
59
|
-
@base.trace
|
60
|
-
end
|
61
|
-
|
62
|
-
# Set the tracing flag; if true, API requests and responses will be
|
63
|
-
# printed out.
|
64
|
-
def trace=(bool)
|
65
|
-
@base.trace = bool
|
66
|
-
end
|
67
|
-
|
68
|
-
# The current log. See +log=+.
|
69
|
-
def log
|
70
|
-
@base.log
|
71
|
-
end
|
72
|
-
|
73
|
-
# Set the logging mode. Mode can be one of:
|
74
|
-
#
|
75
|
-
# [+String+] Name of a file to log the last 10 requests to.
|
76
|
-
# [+Array+] Array to append with log data (a Hash).
|
77
|
-
# [+IO+] An IO object to write to.
|
78
|
-
# [+false+] No logging.
|
79
|
-
def log=(mode)
|
80
|
-
@base.log = mode
|
81
|
-
end
|
82
|
-
|
83
35
|
# The currently authenticated user.
|
84
36
|
def current_user
|
85
37
|
return unless token
|
@@ -92,11 +44,6 @@ module CFoundry::V2
|
|
92
44
|
end
|
93
45
|
end
|
94
46
|
|
95
|
-
# Cloud metadata
|
96
|
-
def info
|
97
|
-
@base.info
|
98
|
-
end
|
99
|
-
|
100
47
|
def login(username, password)
|
101
48
|
@current_organization = nil
|
102
49
|
@current_space = nil
|
data/lib/cfoundry/version.rb
CHANGED
@@ -8,11 +8,11 @@ describe CFoundry::RestClient do
|
|
8
8
|
describe '#request' do
|
9
9
|
let(:path) { "some-path" }
|
10
10
|
let(:url) { "#{target}/#{path}" }
|
11
|
-
let(:
|
11
|
+
let(:verb) { "GET" }
|
12
12
|
let(:options) { {} }
|
13
13
|
|
14
|
-
def check_request(
|
15
|
-
request_stub = stub_request(
|
14
|
+
def check_request(verb = :get, &block)
|
15
|
+
request_stub = stub_request(verb, url).to_return do |req|
|
16
16
|
block.call(req)
|
17
17
|
{}
|
18
18
|
end
|
@@ -20,10 +20,10 @@ describe CFoundry::RestClient do
|
|
20
20
|
expect(request_stub).to have_been_requested
|
21
21
|
end
|
22
22
|
|
23
|
-
subject { rest_client.request(
|
23
|
+
subject { rest_client.request(verb, path, options) }
|
24
24
|
|
25
25
|
describe 'headers' do
|
26
|
-
%w[Authorization
|
26
|
+
%w[Authorization X-Request-Id Content-Type].each do |header_name|
|
27
27
|
it "should not include the #{header_name} by default" do
|
28
28
|
check_request do |req|
|
29
29
|
expect(req.headers).not_to have_key(header_name)
|
@@ -65,8 +65,8 @@ describe CFoundry::RestClient do
|
|
65
65
|
end
|
66
66
|
|
67
67
|
context "when the payload is a hash (i.e. multipart upload)" do
|
68
|
-
let(:
|
69
|
-
let(:options) { {
|
68
|
+
let(:verb) { "PUT" }
|
69
|
+
let(:options) { {:payload => {"key" => "value"}} }
|
70
70
|
|
71
71
|
it 'includes a nonzero content length' do
|
72
72
|
check_request(:put) do |req|
|
@@ -78,7 +78,7 @@ describe CFoundry::RestClient do
|
|
78
78
|
|
79
79
|
context "when params are passed" do
|
80
80
|
context "when params is an empty hash" do
|
81
|
-
let(:options) { {
|
81
|
+
let(:options) { {:params => {}} }
|
82
82
|
|
83
83
|
it "does not add a query string delimiter (the question mark)" do
|
84
84
|
request_stub = stub_request(:get, "https://api.cloudfoundry.com/some-path")
|
@@ -88,7 +88,7 @@ describe CFoundry::RestClient do
|
|
88
88
|
end
|
89
89
|
|
90
90
|
context "when params has values" do
|
91
|
-
let(:options) { {
|
91
|
+
let(:options) { {:params => {"key" => "value"}} }
|
92
92
|
|
93
93
|
it "appends a query string and delimiter" do
|
94
94
|
request_stub = stub_request(:get, "https://api.cloudfoundry.com/some-path?key=value")
|
@@ -119,16 +119,6 @@ describe CFoundry::RestClient do
|
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
122
|
-
context 'and the proxy is set' do
|
123
|
-
before { rest_client.instance_variable_set(:@proxy, "some proxy") }
|
124
|
-
|
125
|
-
it 'should include X-Request-Id in the header' do
|
126
|
-
check_request do |req|
|
127
|
-
expect(req.headers["Proxy-User"]).to eq "some proxy"
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
122
|
context 'and the content is passed in' do
|
133
123
|
let(:options) { {:content => "text/xml"} }
|
134
124
|
|
@@ -149,7 +139,7 @@ describe CFoundry::RestClient do
|
|
149
139
|
end
|
150
140
|
|
151
141
|
context 'and it overrides an existing one' do
|
152
|
-
let(:options) { {
|
142
|
+
let(:options) { {:content => "text/xml", :headers => {"Content-Type" => "text/html"}} }
|
153
143
|
|
154
144
|
it 'uses the custom header' do
|
155
145
|
check_request do |req|
|
@@ -191,7 +181,7 @@ describe CFoundry::RestClient do
|
|
191
181
|
before do
|
192
182
|
stub_request(:get, url).to_return({
|
193
183
|
:status => 201,
|
194
|
-
:headers => {
|
184
|
+
:headers => {"Content-Type" => "application/json"},
|
195
185
|
:body => '{ "foo": 1 }'
|
196
186
|
})
|
197
187
|
end
|
@@ -202,11 +192,11 @@ describe CFoundry::RestClient do
|
|
202
192
|
end
|
203
193
|
|
204
194
|
describe "the returned request hash" do
|
205
|
-
it "returns a hash of :headers, :url, :body and :
|
195
|
+
it "returns a hash of :headers, :url, :body and :verb" do
|
206
196
|
expect(subject[0]).to eq({
|
207
197
|
:url => url,
|
208
198
|
:method => "GET",
|
209
|
-
:headers => {
|
199
|
+
:headers => {"Content-Length" => 0},
|
210
200
|
:body => nil
|
211
201
|
})
|
212
202
|
end
|
@@ -216,7 +206,7 @@ describe CFoundry::RestClient do
|
|
216
206
|
it "returns a hash of :headers, :status, :body" do
|
217
207
|
expect(subject[1]).to eq({
|
218
208
|
:status => "201",
|
219
|
-
:headers => {
|
209
|
+
:headers => {"content-type" => "application/json"},
|
220
210
|
:body => '{ "foo": 1 }'
|
221
211
|
})
|
222
212
|
end
|
@@ -264,12 +254,12 @@ describe CFoundry::RestClient do
|
|
264
254
|
describe 'trace' do
|
265
255
|
before do
|
266
256
|
rest_client.trace = true
|
267
|
-
stub_request(:get, url).to_return(:status => 200, :headers => {
|
257
|
+
stub_request(:get, url).to_return(:status => 200, :headers => {"content-type" => "application/json"}, :body => '{"some": "json"}')
|
268
258
|
end
|
269
259
|
|
270
260
|
it "prints the request and the response" do
|
271
|
-
mock(rest_client).print_request({:headers=>{"Content-Length"=>0}, :url=>"https://api.cloudfoundry.com/some-path", :method=>"GET", :body=>nil})
|
272
|
-
mock(rest_client).print_response({
|
261
|
+
mock(rest_client).print_request({:headers => {"Content-Length" => 0}, :url => "https://api.cloudfoundry.com/some-path", :method => "GET", :body => nil})
|
262
|
+
mock(rest_client).print_response({:status => "200", :headers => {"content-type" => "application/json"}, :body => '{"some": "json"}'})
|
273
263
|
subject
|
274
264
|
end
|
275
265
|
end
|
@@ -278,7 +268,7 @@ describe CFoundry::RestClient do
|
|
278
268
|
before do
|
279
269
|
stub_request(:post, "https://api.cloudfoundry.com/apps").to_return(
|
280
270
|
:status => 301,
|
281
|
-
:headers => {
|
271
|
+
:headers => {"location" => "https://api.cloudfoundry.com/apps/some-guid"}
|
282
272
|
)
|
283
273
|
stub_request(:get, "https://api.cloudfoundry.com/apps/some-guid").to_return(
|
284
274
|
:status => 200,
|
@@ -296,4 +286,86 @@ describe CFoundry::RestClient do
|
|
296
286
|
end
|
297
287
|
end
|
298
288
|
end
|
289
|
+
|
290
|
+
describe CFoundry::RestClient::HTTPFactory do
|
291
|
+
describe ".create" do
|
292
|
+
let(:http_proxy) { '' }
|
293
|
+
let(:https_proxy) { '' }
|
294
|
+
let(:target_uri) { "http://cloudfoundry.com" }
|
295
|
+
|
296
|
+
subject { CFoundry::RestClient::HTTPFactory.create(URI.parse(target_uri), http_proxy, https_proxy) }
|
297
|
+
|
298
|
+
context "when no proxy URI is set" do
|
299
|
+
it "should return an instance of the plain Net:HTTP class" do
|
300
|
+
expect(subject).to be_instance_of(Net::HTTP)
|
301
|
+
expect(subject.use_ssl?).to be_false
|
302
|
+
expect(subject.proxy?).to_not be_true
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
context "when the target is an https URI" do
|
307
|
+
let(:target_uri) { "https://cloudfoundry.com" }
|
308
|
+
it "should return an instance of the plain Net:HTTP class with use_ssl" do
|
309
|
+
expect(subject).to be_instance_of(Net::HTTP)
|
310
|
+
expect(subject.use_ssl?).to be_true
|
311
|
+
expect(subject.proxy?).to_not be_true
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
context "when a http proxy URI without user/password is set " do
|
316
|
+
let(:http_proxy) { "http://exapmle.com:8080" }
|
317
|
+
|
318
|
+
it "should return an instance of the proxy class" do
|
319
|
+
expect(subject.proxy?).to be_true
|
320
|
+
expect(subject.proxy_address).to eql("exapmle.com")
|
321
|
+
expect(subject.proxy_port).to eql(8080)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
context "when a http proxy URI with user/password is set " do
|
326
|
+
let(:http_proxy) { "http://user:pass@exapmle.com:8080" }
|
327
|
+
|
328
|
+
it "should return an instance of the proxy class" do
|
329
|
+
expect(subject.proxy?).to be_true
|
330
|
+
expect(subject.proxy_user).to eql("user")
|
331
|
+
expect(subject.proxy_pass).to eql("pass")
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
context "when a https proxy URI is set and the target is an https URI" do
|
336
|
+
let(:target_uri) { "https://cloudfoundry.com" }
|
337
|
+
let(:https_proxy) { "http://exapmle.com:8080" }
|
338
|
+
|
339
|
+
it "should return an instance of the proxy class" do
|
340
|
+
expect(subject.proxy?).to be_true
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
context "when a https proxy URI is set and the target is an http URI" do
|
345
|
+
let(:target_uri) { "http://cloudfoundry.com" }
|
346
|
+
let(:https_proxy) { "http://exapmle.com:8080" }
|
347
|
+
|
348
|
+
it "should return an instance of the plain Net:HTTP class" do
|
349
|
+
expect(subject.proxy?).to be_nil
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
context "when a http proxy URI is set and the target is an https URI" do
|
354
|
+
let(:target_uri) { "https://cloudfoundry.com" }
|
355
|
+
let(:http_proxy) { "http://exapmle.com:8080" }
|
356
|
+
|
357
|
+
it "should return an instance of the plain Net:HTTP class" do
|
358
|
+
expect(subject.proxy?).to be_nil
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context "when an invalid proxy URI is set" do
|
363
|
+
let(:http_proxy) { "invalid URI" }
|
364
|
+
|
365
|
+
it "should raise an error" do
|
366
|
+
expect { subject }.to raise_error(URI::InvalidURIError)
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
299
371
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cfoundry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.0.
|
4
|
+
version: 0.7.0.rc4
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-04-
|
13
|
+
date: 2013-04-18 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: multipart-post
|
@@ -337,7 +337,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
337
337
|
version: '0'
|
338
338
|
segments:
|
339
339
|
- 0
|
340
|
-
hash:
|
340
|
+
hash: -1868647362048337805
|
341
341
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
342
342
|
none: false
|
343
343
|
requirements:
|