#16705 closed Bug (fixed)
r13746 makes invalid assumption that QUERY_STRING exists
Reported by: | raylu | Owned by: | Aymeric Augustin |
---|---|---|---|
Component: | Generic views | Version: | dev |
Severity: | Release blocker | Keywords: | |
Cc: | preston@… | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
r13746 (from #9966) makes the assumption that QUERY_STRING exists. As this is a bad assumption, please apply the attached patch.
See also: #9435.
Attachments (2)
Change History (16)
by , 13 years ago
Attachment: | 13746_query_string.patch added |
---|
comment:1 by , 13 years ago
Easy pickings: | set |
---|---|
Needs tests: | set |
Patch needs improvement: | set |
Severity: | Normal → Release blocker |
Triage Stage: | Unreviewed → Accepted |
Patch needs tests.
A patch is also required against the new-style class-based views, as it makes the same bad (albeit, almost universally honored) assumption.
Technically this is a release blocker too, since it is a new feature in the previous release.
comment:2 by , 13 years ago
This one line change is tested by the same tests as the rest of r13746.
It does not make the assumption since .get() returns None rather than throwing an exception. The None is checked on the very next line.
comment:3 by , 13 years ago
@raylu -- Your claim is demonstrably false. If it were true, there would be a failing case in the test suite.
The case of query_string=True and query_string=False may be tested; but the non-existence of QUERY_STRING in the WSGI environment *isn't* tested, because the Django test client sets QUERY_STRING by default. We need a test that demonstrates that if QUERY_STRING *isn't* in the environment, the current code fails, but your patch makes the test pass.
comment:4 by , 13 years ago
Oh. I see what you mean.
I'm not very familiar with how to write a Django test nor have I any idea what the new class-based views are, so I'll step down.
comment:5 by , 13 years ago
Owner: | changed from | to
---|
comment:6 by , 13 years ago
Easy pickings: | unset |
---|---|
Patch needs improvement: | unset |
I had to refactor the test client a bit to write tests for this issue. I modified the default environ
dictionary used by django.test.client.RequestFactory
to contain exactly the variables required by the WSGI spec (plus HTTP_COOKIE
because we want to support coookies here). The test suite still passes :)
This change is slightly backwards incompatible. If third-party code uses Django's RequestFactory
or Client
for testing, and contains bugs similar to this one (ie. rely on a variable whose presence isn't guaranteed), its tests may fail after this change. I think this minor incompatibility is acceptable in the context of a bug fix. We could even argue it's a good thing to reveal unnoticed bugs.
I made two other small changes:
CommonMiddleware
usedif request.GET:
to test if there is a query string, and then accessedrequest.META['QUERY_STRING']
. I replaced the check with:if request.META.get('QUERY_STRING', ''):
to make it obvious that it's safe to accessrequest.META['QUERY_STRING']
at the next line. This changes very subtly the behavior of "append slash" and "prepend www" redirects. Previously, invalid query strings (like'&'
) wouldn't be passed on. I can't say if it was intentional. Now they are. It's really an edge case and I think it's worth making this code more explicit. If you disagree, just don't commit this part.- I stumbled upon an unrelated typo in the generic_views tests and fixed it.
by , 13 years ago
Attachment: | 16705.patch added |
---|
comment:7 by , 13 years ago
Cc: | added |
---|
comment:8 by , 13 years ago
Needs tests: | unset |
---|---|
Triage Stage: | Accepted → Ready for checkin |
There could be objections to the changes to the test client, however they seem coupled pretty strongly to testing this patch.
There are a couple small other fixes tacked in, these seem minor enough to allow as riders to this patch.
patch applies to trunk@16829 - tests pass
follow-up: 11 comment:9 by , 13 years ago
It seems like in django/middleware/common.py what you really want is
if 'QUERY_STRING' in request.META:
Everywhere else,
args = request.META.get('QUERY_STRING')
seems to make more sense since the check on the next line is merely if args
comment:10 by , 13 years ago
Description: | modified (diff) |
---|
comment:11 by , 13 years ago
Replying to raylu:
It seems like in django/middleware/common.py what you really want is
if 'QUERY_STRING' in request.META:
The code is written that way on purpose: if request.META['QUERY_STRING']
is the empty string, I don't want to append a query string.
Thanks for the review!
comment:14 by , 13 years ago
Sorry, I meant to reference #16716, not this ticket, in the commit message above.
don't assume QUERY_STRING exists