Opened 4 years ago

Closed 4 years ago

#31494 closed New feature (fixed)

Allow test Client to re-use query string for non-GET requests when following 307/308 redirects.

Reported by: Max Crowe Owned by: Ahmad Abdallah
Component: Testing framework Version: dev
Severity: Normal Keywords: test client redirect
Cc: Ahmad Abdallah Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

If an application uses an HTTP 307 or 308 response to redirect /foo/ to /bar/?a=b, when the test client is instructed to follow redirects, the ultimate request will be to /bar/ (with no query string). This is due to the fact that the test client only examines the query portion of the response URL if the HTTP status is not 307 or 308:

if response.status_code in (HTTPStatus.TEMPORARY_REDIRECT, HTTPStatus.PERMANENT_REDIRECT):
    # Preserve request method post-redirect for 307/308 responses.
    request_method = getattr(self, response.request['REQUEST_METHOD'].lower())
else:
    request_method = self.get
    data = QueryDict(url.query)
    content_type = None

The test client should respect query strings indicated in redirect URLs, even if the request method is something other than GET or HEAD.

Change History (10)

comment:1 by Carlton Gibson, 4 years ago

Summary: Test client discards query string when following 307 or 308 redirectsAllow test Client to re-use query string for non-GET requests when following 307/308 redirects.
Triage Stage: UnreviewedAccepted
Type: UncategorizedNew feature

OK, so there's a valid use-case here I think. One should be able to explicitly pass the query string when creating the redirect response. Such as:

HttpResponseRedirect("/post_view/?hello=world", status=307)

Expecting both the original POST data and the query string to be resubmitted when following the redirect. (Assuming a POST request in the first place.)

Examining the test client behaviour, the redirect_chain is correct (e.g. response.redirect_chain[0] gives ('/post_view/?hello=world', 307)) but the final request query string is empty, as per the report.

_handle_redirects() receives the correct request, including the query string, but this gets dropped by the urlsplit call, and as Max says is not then reused.

Where method != 'GET' path should have the query parameters re-appended in this case.

I'll mark this a new feature since it's never been supported. (Arguably could have been part of 272f685794de0b8dead220ee57b30e65c9aa097c but...)

comment:2 by Max Crowe, 4 years ago

The test client in Django 2.0 would actually reuse the query string as expected in this scenario; however, this was sort of a consequence of it failing to preserve the request method for 307 and 308 redirects.

comment:3 by Ahmad Abdallah, 4 years ago

Cc: Ahmad Abdallah added
Owner: changed from nobody to Ahmad Abdallah
Status: newassigned

comment:4 by Ahmad Abdallah, 4 years ago

Has patch: set

comment:5 by Ahmad Abdallah, 4 years ago

Has patch: unset

As stated on the PR, this patch is incorrect. Fixing it now.

comment:6 by Ahmad Abdallah, 4 years ago

Has patch: set

comment:7 by Mariusz Felisiak, 4 years ago

Patch needs improvement: set

comment:8 by Ahmad A. Hussein, 4 years ago

Patch needs improvement: unset
Version: 3.0master

comment:9 by Mariusz Felisiak <felisiak.mariusz@…>, 4 years ago

In 6425fd3:

Refs #31494 -- Added test for query strings for GET/HEAD requests when following HTTP 307/308 redirects in test client.

comment:10 by Mariusz Felisiak <felisiak.mariusz@…>, 4 years ago

Resolution: fixed
Status: assignedclosed

In 7c947f0:

Fixed #31494 -- Preserved query strings when following HTTP 307/308 redirects in test client.

Note: See TracTickets for help on using tickets.
Back to Top