Skip to content

Commit

Permalink
Merge pull request #581 from pablobm/generic-allow-descriptor
Browse files Browse the repository at this point in the history
Generic `:allow` descriptor
  • Loading branch information
bblimke committed Feb 6, 2016
2 parents 029d4b2 + 828170c commit d428f68
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 43 deletions.
59 changes: 52 additions & 7 deletions README.md
Expand Up @@ -462,22 +462,67 @@ Net::HTTP.get('www.something.com', '/') # ===> Failure
Net::HTTP.get('localhost:9887', '/') # ===> Allowed. Perhaps to Selenium?
```

### External requests can be disabled while allowing any hostname or port or parts thereof
### External requests can be disabled while allowing specific requests

Allowed requests can be specified in a number of ways.

With a `String` specifying a host name:

```ruby
WebMock.disable_net_connect!(:allow => 'www.example.org')

RestClient.get('www.something.com', '/') # ===> Failure
RestClient.get('www.example.org', '/') # ===> Allowed
RestClient.get('www.example.org:8080', '/') # ===> Allowed
```

With a `String` specifying a host name and a port:

```ruby
WebMock.disable_net_connect!(:allow => "www.example.org:8080")
WebMock.disable_net_connect!(:allow => 'www.example.org:8080')

RestClient.get('www.something.com', '/') # ===> Failure
RestClient.get('www.example.org', '/') # ===> Failure
RestClient.get('www.example.org:8080', '/') # ===> Allowed
```

With a `Regexp` matching the URI:

```ruby
WebMock.disable_net_connect!(:allow => %r{ample.org/foo})

RestClient.get('www.example.org', '/') # ===> Failure.
RestClient.get('www.example.org', '/foo/bar') # ===> Allowed
RestClient.get('sample.org', '/foo') # ===> Allowed
RestClient.get('sample.org', '/bar') # ===> Failure
```

RestClient.get('www.example.org:8080', '/') # ===> Allowed
With an object that responds to `#call`, receiving a `URI` object and returning a boolean:

WebMock.disable_net_connect!(:allow => /ample.org/)
```ruby
blacklist = ['google.com', 'facebook.com', 'apple.com']
allowed_sites = lambda{|uri|
blacklist.none?{|site| uri.host.include?(site) }
}
WebMock.disable_net_connect!(:allow => allowed_sites)

RestClient.get('www.example.org', '/') # ===> Allowed
RestClient.get('www.facebook.com', '/') # ===> Failure
RestClient.get('apple.com', '/') # ===> Failure
```

WebMock.disable_net_connect!(:allow => [/ample.org/, /googl/])
With an `Array` of any of the above:

RestClient.get('www.example.org', '/') # ===> Allowed
```ruby
WebMock.disable_net_connect!(:allow => [
lambda{|uri| uri.host.length % 2 == 0 },
/ample.org/,
'bbc.co.uk',
])

RestClient.get('www.example.org', '/') # ===> Allowed
RestClient.get('bbc.co.uk', '/') # ===> Allowed
RestClient.get('bbc.com', '/') # ===> Allowed
RestClient.get('www.bbc.com', '/') # ===> Failure
```

## Connecting on Net::HTTP.start
Expand Down
4 changes: 4 additions & 0 deletions lib/webmock/webmock.rb
Expand Up @@ -72,6 +72,10 @@ def self.net_connect_explicit_allowed?(allowed, uri=nil)
when String
allowed == uri.host ||
allowed == "#{uri.host}:#{uri.port}"
else
if allowed.respond_to?(:call)
allowed.call(uri)
end
end
end

Expand Down
180 changes: 144 additions & 36 deletions spec/acceptance/shared/allowing_and_disabling_net_connect.rb
Expand Up @@ -88,64 +88,172 @@
end
end

describe "is not allowed with exception for allowed domains" do
let(:host_with_port){ WebMockServer.instance.host_with_port }
describe "is not allowed, with exceptions" do
describe "allowing by host string" do
before :each do
WebMock.disable_net_connect!(:allow => 'httpstat.us')
end

before(:each) do
WebMock.disable_net_connect!(:allow => ["www.example.org", "httpstat.us", host_with_port])
end
context "when the host is not allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, 'disallowed.example.com/foo').to_return(:body => "abc")
expect(http_request(:get, 'http://disallowed.example.com/foo').body).to eq("abc")
end

context "when the host is not allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, "www.example.com").to_return(:body => "abc")
expect(http_request(:get, "http://www.example.com/").body).to eq("abc")
it "should raise exception if request was not stubbed" do
expect {
http_request(:get, 'http://disallowed.example.com/')
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://disallowed.example.com))
end
end

it "should raise exception if request was not stubbed" do
expect {
http_request(:get, "http://www.example.com/")
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/))
context "when the host is allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, 'httpstat.us/200').to_return(:body => "abc")
expect(http_request(:get, "http://httpstat.us/200").body).to eq("abc")
end

# WARNING: this makes a real HTTP request!
it "should make a real request to allowed host", :net_connect => true do
expect(http_request(:get, "http://httpstat.us/200").status).to eq('200')
end
end
end

context "when the host with port is not allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, "http://localhost:2345").to_return(:body => "abc")
expect(http_request(:get, "http://localhost:2345/").body).to eq("abc")
describe "allowing by host:port string" do
def replace_with_different_port(uri)
uri.sub(%r{:(\d+)}){|m0, m1| ':' + ($~[1].to_i + 1).to_s }
end

let(:allowed_host_with_port) { WebMockServer.instance.host_with_port }
let(:disallowed_host_with_port) { replace_with_different_port(allowed_host_with_port) }

before :each do
WebMock.disable_net_connect!(:allow => allowed_host_with_port)
end

context "when the host is not allowed" do
it "should return stubbed response if request was stubbed" do
request_url = "http://#{disallowed_host_with_port}/foo"
stub_request(:get, request_url).to_return(:body => "abc")
expect(http_request(:get, request_url).body).to eq("abc")
end

it "should raise exception if request was not stubbed" do
request_url = "http://#{disallowed_host_with_port}/foo"
expect {
http_request(:get, request_url)
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET #{request_url}))
end
end

it "should raise exception if request was not stubbed" do
expect {
http_request(:get, "http://localhost:2345/")
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://localhost:2345/))
context "when the host is allowed" do
it "should return stubbed response if request was stubbed" do
request_url = "http://#{allowed_host_with_port}/foo"
stub_request(:get, request_url).to_return(:body => "abc")
expect(http_request(:get, request_url).body).to eq('abc')
end

it "should make a real request to allowed host", :net_connect => true do
request_url = "http://#{allowed_host_with_port}/foo"
expect(http_request(:get, request_url).status).to eq('200')
end
end
end

context "when the host is allowed" do
it "should raise exception if request was not stubbed" do
expect {
http_request(:get, "http://www.example.com/")
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://www.example.com/))
describe "allowing by regular expression" do
before :each do
WebMock.disable_net_connect!(:allow => %r{httpstat})
end

context "when the host is not allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, 'disallowed.example.com/foo').to_return(:body => "abc")
expect(http_request(:get, 'http://disallowed.example.com/foo').body).to eq("abc")
end

it "should raise exception if request was not stubbed" do
expect {
http_request(:get, 'http://disallowed.example.com/')
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://disallowed.example.com))
end
end

it "should make a real request to allowed host", :net_connect => true do
expect(http_request(:get, "http://httpstat.us/200").status).to eq("200")
context "when the host is allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, 'httpstat.us/200').to_return(:body => "abc")
expect(http_request(:get, "http://httpstat.us/200").body).to eq("abc")
end

# WARNING: this makes a real HTTP request!
it "should make a real request to allowed host", :net_connect => true do
expect(http_request(:get, "http://httpstat.us/200").status).to eq('200')
end
end
end

context "when the host with port is allowed" do
it "should make a real request to allowed host", :net_connect => true do
expect(http_request(:get, "http://#{host_with_port}/").status).to eq("200")
describe "allowing by a callable" do
before :each do
WebMock.disable_net_connect!(:allow => lambda{|url| url.to_str.include?('httpstat') })
end

context "when the host is not allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, 'disallowed.example.com/foo').to_return(:body => "abc")
expect(http_request(:get, 'http://disallowed.example.com/foo').body).to eq("abc")
end

it "should raise exception if request was not stubbed" do
expect {
http_request(:get, 'http://disallowed.example.com/')
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://disallowed.example.com))
end
end

context "when the host is allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, 'httpstat.us/200').to_return(:body => "abc")
expect(http_request(:get, "http://httpstat.us/200").body).to eq("abc")
end

# WARNING: this makes a real HTTP request!
it "should make a real request to allowed host", :net_connect => true do
expect(http_request(:get, "http://httpstat.us/200").status).to eq('200')
end
end
end

context "when the host is allowed but not port" do
it "should make a real request to allowed host", :net_connect => true do
expect {
http_request(:get, "http://localhost:123/")
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://localhost:123/))
describe "allowing by a list of the above" do
before :each do
WebMock.disable_net_connect!(:allow => [lambda{|_| false }, %r{foobar}, 'httpstat.us'])
end

context "when the host is not allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, 'disallowed.example.com/foo').to_return(:body => "abc")
expect(http_request(:get, 'http://disallowed.example.com/foo').body).to eq("abc")
end

it "should raise exception if request was not stubbed" do
expect {
http_request(:get, 'http://disallowed.example.com/')
}.to raise_error(WebMock::NetConnectNotAllowedError, %r(Real HTTP connections are disabled. Unregistered request: GET http://disallowed.example.com))
end
end

context "when the host is allowed" do
it "should return stubbed response if request was stubbed" do
stub_request(:get, 'httpstat.us/200').to_return(:body => "abc")
expect(http_request(:get, "http://httpstat.us/200").body).to eq("abc")
end

# WARNING: this makes a real HTTP request!
it "should make a real request to allowed host", :net_connect => true do
expect(http_request(:get, "http://httpstat.us/200").status).to eq('200')
end
end
end

end
end
end

0 comments on commit d428f68

Please sign in to comment.