Comments (8)
I guess there must be a missing test. I'll look into this and make sure there's a test that covers this, fix it, and make a new release.
Thanks for reporting the problem.
from wsgi-intercept.
I'm unable to replicate this problem. Can you provide a pointer to a failing test or at least more information on your environment where you are seeing the problem (version of requests, version of Python, operating system, etc)?
from wsgi-intercept.
This is within a unix docker container. We are using python2.7. The requests lib is version 2.10.0. I also tried with the latest (2.13.0). Here is a simple script to reproduce it.
import requests
from wsgi_intercept import (http_client_intercept, requests_intercept,
urllib3_intercept, add_wsgi_intercept)
def app(environ, start_response):
url = 'https://play.google.com/store/apps/details'
params = {
'hl': 'en',
'id': 'com.disney.WMW',
}
r = requests.get(url, params=params, timeout=3.0)
start_response('200 OK', [('Content-Type', 'text/html')])
return [r.content]
def make_app():
return app
if __name__ == '__main__':
try:
from wsgiref.simple_server import make_server
httpd = make_server('', 8080, app)
print('Serving on port 8080...')
requests_intercept.install()
urllib3_intercept.install()
http_client_intercept.install()
add_wsgi_intercept('play.google.com', 443, make_app)
httpd.serve_forever()
except KeyboardInterrupt:
requests_intercept.uninstall()
urllib3_intercept.uninstall()
http_client_intercept.uninstall()
print('Goodbye.')
$ python2.7 server.py &
$ curl localhost:8080
Traceback (most recent call last):
File "/usr/lib64/python2.7/wsgiref/handlers.py", line 85, in run
self.result = application(self.environ, self.start_response)
File "server.py", line 12, in app
r = requests.get(url, params=params, timeout=3.0)
File "/usr/lib/python2.7/site-packages/requests/api.py", line 70, in get
return request('get', url, params=params, **kwargs)
File "/usr/lib/python2.7/site-packages/requests/api.py", line 56, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
resp = self.send(prep, **send_kwargs)
File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
r = adapter.send(request, **kwargs)
File "/usr/lib/python2.7/site-packages/requests/adapters.py", line 423, in send
timeout=timeout
File "/usr/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 588, in urlopen
conn = self._get_conn(timeout=pool_timeout)
File "/usr/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 250, in _get_conn
return conn or self._new_conn()
File "/usr/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 832, in _new_conn
strict=self.strict, **self.conn_kw)
File "/usr/lib/python2.7/site-packages/wsgi_intercept/_urllib3.py", line 28, in __init__
WSGI_HTTPSConnection.__init__(self, *args, **kwargs)
File "/usr/lib64/python2.7/httplib.py", line 1254, in __init__
source_address)
TypeError: unbound method __init__() must be called with HTTP_WSGIInterceptor instance as first argument (got HTTPS_WSGIInterceptor instance instead)
127.0.0.1 - - [14/Mar/2017 16:16:30] "GET / HTTP/1.1" 500 59
from wsgi-intercept.
Hmmm. Couple of things here. One is that you only need to install one intercept. In this case requests_intercept.install() ought to do the trick. In your own environment if you fix that, you might be able to get things working.
In the example you've provided, however, once you are only using one interceptor you'll see that you're still getting an error, but a different one that your proposed fix does not fix. Instead we get an error in the application which eventually reveals itself to be a maximum recursion problem.
That's because what you're doing here is not something that wsgi-intercept is really expecting: You are intercepting a hostname used by the application that you are intercepting, so the app calls itself, which calls itself, which calls itself...
Does that make any sense?
So my advice at this stage would be to try using just one interceptor and see where that gets you. Also consider using the context manager style of interceptors if that can work for you.
from wsgi-intercept.
Regarding the max recursion issue, yes that makes sense. Using a single interceptor for requests gives me the results I would expect, the problem is when you use a requests interceptor along with an http client interceptor. That's what causes the error. You can use any combination of the other interceptors, you just can't use both HttpClientInterceptor and RequestsInterceptor at the same time.
For our use case the app under test uses 2 or more underlying libraries (e.g. requests, urllib3, httplib). So we need to intercept all of them for mocking http calls.
Here's an example using the context, which gives the same result as using the old style manual install/add_wsgi_itercept.
import requests
from wsgi_intercept.interceptor import RequestsInterceptor, HttpClientInterceptor
def foo1(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b'foo']
def foo():
return foo1
if __name__ == '__main__':
with HttpClientInterceptor(foo, 'somedomain.com'):
with RequestsInterceptor(foo, 'play.google.com', 443):
url = 'https://play.google.com/store/apps/details'
params = {
'hl': 'en',
'id': 'com.disney.WMW',
}
r = requests.get(url, params=params)
print r.content
$ python server.py
Traceback (most recent call last):
File "server.py", line 35, in <module>
r = requests.get(url, params=params)
File "/usr/lib/python2.7/site-packages/requests/api.py", line 70, in get
return request('get', url, params=params, **kwargs)
File "/usr/lib/python2.7/site-packages/requests/api.py", line 56, in request
return session.request(method=method, url=url, **kwargs)
File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 488, in request
resp = self.send(prep, **send_kwargs)
File "/usr/lib/python2.7/site-packages/requests/sessions.py", line 609, in send
r = adapter.send(request, **kwargs)
File "/usr/lib/python2.7/site-packages/requests/adapters.py", line 423, in send
timeout=timeout
File "/usr/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 588, in urlopen
conn = self._get_conn(timeout=pool_timeout)
File "/usr/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 250, in _get_conn
return conn or self._new_conn()
File "/usr/lib/python2.7/site-packages/requests/packages/urllib3/connectionpool.py", line 832, in _new_conn
strict=self.strict, **self.conn_kw)
File "/usr/lib/python2.7/site-packages/wsgi_intercept/_urllib3.py", line 28, in __init__
WSGI_HTTPSConnection.__init__(self, *args, **kwargs)
File "/usr/lib64/python2.7/httplib.py", line 1254, in __init__
source_address)
TypeError: unbound method __init__() must be called with HTTP_WSGIInterceptor instance as first argument (got HTTPS_WSGIInterceptor instance instead)
If you replace HttpClientInteceptor
with any of the others like Urllib3Interceptor
it works as expected.
from wsgi-intercept.
Interesting. Your use of wsgi-intercept (using different interceptors at the same time) is a bit different from the common use case (where you use the interceptor simply to allow mounting a wsgi app on a fake socket and test it with one client type at any given time). But since your suggested change fixes it and doesn't seem to break anything else I'll go ahead and make it and do a new release. Thanks for persisting in answering my questions.
from wsgi-intercept.
doesn't seem to break anything else
This isn't the case. When I make your suggested change it causes several failures in the test suite under py27 and in py35 the tests give up immediately because of
E TypeError: Cannot create a consistent method resolution
E order (MRO) for bases HTTPSConnection, HTTP_WSGIInterceptor, WSGI_HTTPConnection
The underlying issue here is that all the usual client libraries end up eventually using the http.client or httplib code so if you have already monkeypatched in requests and then want to monkey patch in http.client too, the thing being monkey patched is the wrong type: it has already been patched by the other interceptor.
So the end result of this is what I said earlier: use one interceptor at a time. If you need to test different clients, only intercept the one you are testing during any given test.
If I'm still missing something please let me know, but please keep in mind that the existing tests and use cases need to continue working, so try your ideas out on the code and the tests that already exist. Thanks.
from wsgi-intercept.
Thanks for the feedback and quick responses!
from wsgi-intercept.
Related Issues (20)
- Including LICENSE file in the code repository and Adding it in the Manifest file HOT 4
- unexpected keyword argument 'source_address' HOT 3
- Please allow to disable internet tests HOT 3
- wsgi_intercept.make_environ turns headers into unicode HOT 3
- When using the url arg to an Interceptor, if there is no port in the url an error happens
- wsgi-intercept should build in some character encoding checks
- Write ignores response body when first item in iterable is an empty string HOT 1
- Logs / errors are lost due to `wsgi.errors` not extracted HOT 4
- Interceptor.uninstall_interceptor turns off intercept for all intercepts using the same module
- Pypi sdist tarball doesn't have README.rst HOT 3
- Missing 2 required positional arguments: 'environ' and 'start_response' with Django 2.2 HOT 4
- With httplib2 0.14.0 many tests fail HOT 9
- HTTPS connections with Requests library don't support verify=False to outside domains HOT 7
- Support aiohttp HOT 2
- Simple example fails with Python 2 HOT 5
- PEP517 HOT 4
- Incompatibility with pytest 7.2.0 HOT 2
- support urllib3 > 2 HOT 1
- drop support for python 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from wsgi-intercept.