New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose redirect chain from test client #763
Comments
The final location lives on the response object. |
I don't see any attributes for it. What property are we talking about? http://werkzeug.pocoo.org/docs/0.10/wrappers/#werkzeug.wrappers.BaseResponse |
Ah sorry, I misremembered. |
No worries. I felt like it should exist as well. What is the interface you would consider adding? I am open to writing a PR for this. |
I don't really know. I think keeping the API similar to requests is useful. On Wed, Aug 19, 2015 at 01:49:13PM -0700, Todd Wolfson wrote:
|
I was hoping there was a way to define https://github.com/cobrateam/splinter/blob/0.7.3/splinter/driver/djangoclient.py#L94-L98 For my interim hack/patch, I have extended on cobrateam/splinter@cobrateam:5317b71...underdogio:f7e0da6#diff-df553efba1487ab0f96b4053dee86c25R87 |
This comment has been minimized.
This comment has been minimized.
I looked into this too, and it's tricky to fit this in to the existing behavior. The problem is that what we return isn't flexible. Either we return a I understand why we allow returning a tuple, since that maps directly to WSGI I think I have a compromise, but someone would need to try to implement it to see if it's viable. I'd like to always return a Speaking of |
@davidism For us to hook up the |
This is a Werkzeug issue, you can change the client code directly. 😉 |
@davidism this is what I was thinking. It adds the redirect_chain to the response. Not a super elegant solution though😅 ....
class Client():
def open(self, *args, **kwargs):
as_tuple = kwargs.pop("as_tuple", False)
buffered = kwargs.pop("buffered", False)
follow_redirects = kwargs.pop("follow_redirects", False)
environ = None
if not kwargs and len(args) == 1:
if isinstance(args[0], EnvironBuilder):
environ = args[0].get_environ()
elif isinstance(args[0], dict):
environ = args[0]
if environ is None:
builder = EnvironBuilder(*args, **kwargs)
try:
environ = builder.get_environ()
finally:
builder.close()
response = self.run_wsgi_app(environ.copy(), buffered=buffered)
# handle redirects
redirect_chain = []
while 1:
status_code = int(response[1].split(None, 1)[0])
if (
status_code not in {301, 302, 303, 305, 307, 308}
or not follow_redirects
):
break
# Exhaust intermediate response bodies to ensure middleware
# that returns an iterator runs any cleanup code.
if not buffered:
for _ in response[0]:
pass
new_location = response[2]["location"]
new_redirect_entry = (new_location, status_code)
if new_redirect_entry in redirect_chain:
raise ClientRedirectError("loop detected")
redirect_chain.append(new_redirect_entry)
environ, response = self.resolve_redirect(
response, new_location, environ, buffered=buffered
)
if self.response_wrapper is not None:
response = self.response_wrapper(*response)
setattr(response, 'redirect_chain', redirect_chain) # This will enable us to access the redirect chain
if as_tuple:
return environ, response
return response |
Makes sense. My comment above was addressing how we return the chain. I want to avoid setting extra attributes (using |
@davidism Have you been able to take a look at the PR? |
I am currently with a project,
splinter
, which emulates browser-like interactions via the Flask/Werkzeug test client. Their current URL behavior is broken redirects as its currently serving the originally requested URL, not the final one.Currently, the test client has no way of telling what the final request location was (nor its hops along the way). I was wondering if we could return the
redirect_chain
somehow (e.g. as an attribute of the Response object).https://github.com/mitsuhiko/werkzeug/blob/0.10.4/werkzeug/test.py#L744-L760
The text was updated successfully, but these errors were encountered: