diff --git a/README.md b/README.md
index 6a8f92a..1b9521a 100644
--- a/README.md
+++ b/README.md
@@ -103,9 +103,25 @@ proxy.stub('https://example.com:443/secure/').and_return(:text => 'secrets!!1!')
 #   params:  Query string parameters hash, CGI::escape-style
 #   headers: Headers hash
 #   body:    Request body string
-#
-proxy.stub('https://example.com/proc/').and_return(Proc.new { |params, headers, body|
-  { :text => "Hello, #{params['name'][0]}"}
+#   url:     The actual URL which was requested
+#   method:  The HTTP verb which was requested
+proxy.stub('https://example.com/proc/').and_return(Proc.new { |params, headers, body, url, method|
+  {
+    :code => 200,
+    :text => "Hello, #{params['name'][0]}"
+  }
+})
+
+# You can also use Puffing Billy to intercept requests and responses. Just pass
+# a Proc and use the pass_request method. You can manipulate the request
+# (headers, URL, HTTP method, etc) and also the response from the upstream
+# server.
+proxy.stub('http://example.com/').and_return(Proc.new { |*args|
+  response = pass_request(*args)
+  response[:headers]['Content-Type'] = 'text/plain'
+  response[:body] = 'Hello World!'
+  response[:code] = 200
+  response
 })
 
 # Stub out a POST. Don't forget to allow a CORS request and set the method to 'post'
diff --git a/lib/billy/proxy_request_stub.rb b/lib/billy/proxy_request_stub.rb
index 45f4cc6..d98cd22 100644
--- a/lib/billy/proxy_request_stub.rb
+++ b/lib/billy/proxy_request_stub.rb
@@ -21,7 +21,7 @@ def call(method, url, params, headers, body)
       push_request(method, url, params, headers, body)
 
       if @response.respond_to?(:call)
-        res = @response.call(params, headers, body)
+        res = instance_exec(params, headers, body, url, method, &@response)
       else
         res = @response
       end
@@ -71,6 +71,16 @@ def matches?(method, url)
       end
     end
 
+    def pass_request(params, headers, body, url, method)
+      handler = Billy.proxy.request_handler.handlers[:proxy]
+      response = handler.handle_request(method, url, headers, body)
+      {
+        code: response[:status],
+        body: response[:content],
+        headers: response[:headers]
+      }
+    end
+
     private
 
     attr_writer :requests
diff --git a/spec/lib/billy/proxy_request_stub_spec.rb b/spec/lib/billy/proxy_request_stub_spec.rb
index 7a119ab..7a52348 100644
--- a/spec/lib/billy/proxy_request_stub_spec.rb
+++ b/spec/lib/billy/proxy_request_stub_spec.rb
@@ -157,18 +157,51 @@
       expected_headers = { 'header1' => 'three', 'header2' => 'four' }
       expected_body = 'body text'
 
-      subject.and_return(proc do |params, headers, body|
+      # Required due to the instance_exec implementation
+      subject.extend(RSpec::Matchers)
+
+      subject.and_return(proc do |params, headers, body, url, method|
         expect(params).to eql expected_params
         expect(headers).to eql expected_headers
         expect(body).to eql 'body text'
+        expect(url).to eql 'url'
+        expect(method).to eql 'GET'
         { code: 418, text: 'success' }
       end)
-      expect(subject.call('', '', expected_params, expected_headers, expected_body)).to eql [
+      expect(subject.call('GET', 'url', expected_params, expected_headers, expected_body)).to eql [
         418,
         { 'Content-Type' => 'text/plain' },
         'success'
       ]
     end
+
+    it 'should use a callable with pass_request' do
+      # Add the missing em-synchrony call which is done by
+      # ProxyConnection#handle_request instead.
+      EM.synchrony do
+        # Required due to the instance_exec implementation
+        subject.extend(RSpec::Matchers)
+
+        subject.and_return(proc do |*args|
+          response = pass_request(*args)
+          response[:body] = 'modified'
+          response[:code] = 205
+          response
+        end)
+
+        # The test server can't be used at this scenario due to the limitations
+        # of the Ruby GIL. We cannot use fibers (via eventmachine) and ask
+        # ourself on a different thread to serve a HTTP request. This results
+        # in +fiber called across threads (FiberError)+ errors. Unfortunately
+        # we have to ask an external resource.
+        url = 'http://google.com'
+
+        expect(subject.call('GET', url, {}, {}, 'original')).to eql [
+          205,
+          'modified'
+        ]
+      end
+    end
   end
 
   context '#stub_requests' do