Django: Ticket Query!closed&component=HTTP+handling&order=type The Web framework for perfectionists with deadlines. en-US Django!closed&component=HTTP+handling&order=type Trac 1.0.9 #5797: decorator_from_middleware can cause middleware hooks to run out of correct order. Mon, 22 Oct 2007 21:15:11 GMT jdunck <p> cache_page, gzip_page, and conditional_page all use decorator_from_middleware. </p> <p> decorator_from_middleware wraps the view function to simulate middleware being run on a per-view basis. </p> <p> Here's the interesting bit: </p> <pre class="wiki"> def _wrapped_view(request, *args, **kwargs): if hasattr(middleware, 'process_request'): result = middleware.process_request(request) if result is not None: return result if hasattr(middleware, 'process_view'): result = middleware.process_view(request, view_func, *args, **kwargs) if result is not None: return result try: response = view_func(request, *args, **kwargs) except Exception, e: if hasattr(middleware, 'process_exception'): result = middleware.process_exception(request, e) if result is not None: return result raise if hasattr(middleware, 'process_response'): result = middleware.process_response(request, response) if result is not None: return result return response </pre><p> The problem is that middleware's order is important. Suppose two middleware decorators, A and B, are applied to the same view. </p> <p> The normal flow of middleware processing would be: A.process_request, B.process_request, A.process_view, B.process_view, view, B.process_response, A.process_response. </p> <p> The flow of the *decorated execution* is this: A.process_request, A.process_view, B.process_request, B.process_view, view, B.process_response, A.process_response. </p> <p> This is not yet a real-world issue as far as I know, but seems to be a lurking problem. I think the only reason it hasn't surfaced is that view decorators are fairly uncommon. I don't see a simple way to fix this. </p> Results #14035: Cannot access POST after request.encoding was set to a custom value Fri, 30 Jul 2010 15:43:03 GMT zimnyx <p> Issue happens for multipart/form-data and WSGi handler. </p> <pre class="wiki">#Django trunk r13353. class DetectEncodingMiddleware(object): def process_request(request): # Lets say we define data encoding in POST param called "enc" enc = request.POST['enc'] # request._load_post_and_files() request.encoding = enc # request._set_encoding(): del self._post request.POST # request._load_post_and_files() # raise AttributeError("You cannot set the upload handlers after the upload has been processed."); </pre><p> This issue is related: <a class="closed ticket" href="" title="Bug: Unable to get request.POST after request.get_raw_post_data (closed: duplicate)">#12522</a> </p> Results #14722: @last_modified should ignore lack of etag method when USE_ETAGS is enabled Thu, 18 Nov 2010 17:00:46 GMT lamby <p> Using @last_modified with settings.USE_ETAGS does not work as expected. </p> <p> My goal is to avoid evaluating the view for a select handful of expensive pages based on the Last-Modified header, and globally fallback to saving bandwidth with USE_ETAGS. </p> <p> However, if you enable USE_ETAGS and the @last_modified decorator, the view is still evaluated despite the last_modified_func being a match with If-Modified-Since. This is because the client is providing an ETag header (added because USE_ETAGS is enabled) and django.views.decorators.http.condition uses that etag along with the fact that we did did not provide an etag_func argument as a reason for not returning 304. </p> <p> Patch attached that disables this particular part of the logic if settings.USE_ETAGS is enabled. </p> Results #16674: Django's WSGI Handler should report exceptions to the start_response() callback Mon, 22 Aug 2011 10:42:08 GMT jamesh <p> The WSGI specification allows WSGI applications to pass an exception context to their start_response() callback if the response is being provided by an error handler. </p> <p> This is quite useful for WSGI middleware that collects data about errors: they can log the problem and then pass on the error page generated by the application. </p> <p> Unfortunately, Django's WSGI handler never seems to call start_response() with the third argument, preventing this sort of middleware from seeing errors in Django applications. </p> <p> I think a solution to this would be something like: </p> <ol><li>override handle_uncaught_exception() in WSGIHandler and make it stash exc_info somewhere (on the response object would be hacky but maybe workable). </li><li>after <span class="underline">call</span> invokes get_response(), check for a captured exc_info value. </li><li>if exc_info was captured, pass it to start_response() </li></ol> Results #17235: Multipartparser shouldn't leave the QueryDict mutable Tue, 15 Nov 2011 15:41:51 GMT apollo13 <p> Currently the multipart parser constructs <em>QueryDicts</em> for POST and FILES as mutable. Since we discourage users to change <em>QueryDicts</em> (and don't allow it for GET and normal POST) the parser should change the flag to False before returning it. This way multipart POSTs would be more consistent with normal POSTs which aren't mutable. </p> Results #17834: ETag generated from empty content can break http caching Mon, 05 Mar 2012 15:48:27 GMT paulegan <p> The [source:/django/trunk/django/utils/ patch_response_headers] function will set an ETag header using an md5 hash of the response content. Many responses like redirects can have an empty body and this results in the same ETag for each such response. The response headers may vary but an intermediate cache can serve an incorrect response because the ETag is not unique. </p> <p> A simple solution is to not set ETag if the content is empty - see attached patch. </p> <div class="code"><pre><span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">django.http</span> <span class="kn">import</span> HttpResponseRedirect <span class="o">&gt;&gt;&gt;</span> <span class="kn">from</span> <span class="nn">django.utils.cache</span> <span class="kn">import</span> patch_response_headers <span class="o">&gt;&gt;&gt;</span> r1 <span class="o">=</span> HttpResponseRedirect<span class="p">(</span><span class="s">'/u1'</span><span class="p">)</span> <span class="o">&gt;&gt;&gt;</span> patch_response_headers<span class="p">(</span>r1<span class="p">)</span> <span class="o">&gt;&gt;&gt;</span> r2 <span class="o">=</span> HttpResponseRedirect<span class="p">(</span><span class="s">'/u2'</span><span class="p">)</span> <span class="o">&gt;&gt;&gt;</span> patch_response_headers<span class="p">(</span>r2<span class="p">)</span> <span class="o">&gt;&gt;&gt;</span> r1<span class="p">[</span><span class="s">'ETag'</span><span class="p">]</span> <span class="o">==</span> r2<span class="p">[</span><span class="s">'ETag'</span><span class="p">]</span> <span class="bp">True</span> </pre></div> Results #17955: Uploading a file without using django forms Fri, 23 Mar 2012 02:05:11 GMT alexandre@… <p> Hi, </p> <p> i was trying to upload a file to my django backend without using django forms, but i was not able to it : my file was constantly getting dropped by the multiparser! </p> <p> my multipart/formdata post request has two standard string post values : </p> <p> Content-Disposition: form-data; name="foo" \r\n\r\n </p> <p> and one file : Content-Disposition: form-data; filename="bar"\r\n Content-Type: image/png\r\n\r\n </p> <p> I made it work simply by changing the file this way : </p> <p> Current : </p> <pre class="wiki"> 92 def parse(self): ... 141 try: 142 disposition = meta_data['content-disposition'][1] 143 field_name = disposition['name'].strip() 144 except (KeyError, IndexError, AttributeError): 145 continue </pre><p> New : </p> <pre class="wiki"> def parse(self): ... field_name = '' try: disposition = meta_data['content-disposition'][1] if disposition.has_key('name'): field_name = disposition['name'].strip() else: field_name = disposition['filename'].strip() except (KeyError, IndexError, AttributeError): continue </pre><p> I think the change is pretty straightforward, and would be really nice! </p> Results #19649: Cookie message storage does not set Vary: Cookie Mon, 21 Jan 2013 19:14:22 GMT carljm <p> The cookie storage backend for contrib.messages does not set Vary: Cookie on the response, which means that (in the absence of CSRF protection or sessions or other bits of Django that are likely to set Vary: Cookie) it is possible for users behind a cache to miss messages intended for them, or even for a cache to store a page with a message intended for a single user on it and then serve that page to other users. </p> <p> In practice, it is quite likely that the cookie message store is used along with CSRF protection or contrib.session, in which case Vary: Cookie will be set on most responses anyway, rendering this issue moot. </p> <p> A case could be made that the correct fix here is at an even deeper level; that any access of request.cookies should automatically trigger Vary: Cookie on the response. This follows the same logic as the current behavior of SessionMiddleware to set Vary: Cookie on any response where the session is accessed, but pushes that logic down to the common cookie layer where it really belongs, rather than duplicating it in the cookie message storage. If you are accessing cookies at all on the server side, presumably that means you are making some decision based on the cookie that might affect the response in some way, and if so Vary: Cookie must be set or the response might be cached incorrectly. </p> <p> If we don't make the fix at the request.cookies layer, we are saying that it is the responsibility of the developer to ensure that if they use cookies, they set Vary: Cookie, in which case we ought to make that clear in the docs. Given that it's very difficult to construct a scenario in which it is correct to access cookies but not set Vary: Cookie, I don't see much reason to place this responsibility on the developer. </p> <p> For this reason, I'm setting the component for this bug to "core" rather than "contrib.messages", even though the latter is the only place I know of where Django itself triggers the bug by making use of cookies without setting Vary: Cookie. </p> <p> (Thanks to Florian for presenting the hypothetical case that exposed this bug.) </p> Results #19705: CommonMiddleware handles If-None-Match incorrectly Wed, 30 Jan 2013 23:04:00 GMT aaugustin <p> Two middleware check ETags for unmodified responses: <tt>CommonMiddleware</tt> and <tt>ConditionalGetMiddleware</tt> and they do it inconsistently. </p> <p> If the response's ETag matches the request's If-None-Match: </p> <ul><li><tt>ConditionalGetMiddleware</tt> changes the response code to 304, preserving all headers; the content gets removed later on </li><li><tt>CommonMiddleware</tt> creates a new <tt>HttpResponseNotModified</tt> without content and simply restores the cookies. </li></ul><p> As a consequence, <tt>CommonMiddleware</tt> returns a response without ETag, which is wrong. I detected this with RedBot on a Django site I run. Any site with <tt>USE_ETAGS = True</tt> has this problem. </p> <p> In general, wiping headers sounds like a bad idea. A 304 is supposed to have the same headers as the 200. (Well, the RFC is more complicated, but I think it's the general idea. <a class="ext-link" href=""><span class="icon">​</span>Future versions of HTTP</a> will likely require the Content-Length not to be 0.) </p> <hr /> <p> I believe that <tt>CommonMiddleware</tt> should simply generate the ETag and not handle conditional content removal; that's the job of <tt>ConditionalGetMiddleware</tt>. </p> <p> For example, if one is using GzipMiddleware, the correct response chain is: </p> <ul><li><tt>CommonMiddleware</tt> computes the ETag, </li><li><tt>GzipMiddleware</tt> compresses the content and modifies the ETag, </li><li><tt>ConditionalGetMiddleware</tt> uses the modified ETag to decide if the response was modified or not. </li></ul><p> This is a good reason to keep "ETag generation" and "Etag checking" concerns separate. The same argument applies to any middleware that sets or modifies ETags. </p> <p> Unfortunately, <tt>CommonMiddleware</tt> is documented to "take care of sending Not Modified responses, if appropriate", so this would be a backwards incompatible change. </p> Results #20752: Error signals are not reliable, especially when dealing with database errors Mon, 15 Jul 2013 19:45:47 GMT tal@… <p> In core.handlers.base, unhandled exceptions are processed as such: </p> <pre class="wiki"> except: # Handle everything else, including SuspiciousOperation, etc. # Get the exception info now, in case another exception is thrown later. signals.got_request_exception.send(sender=self.__class__, request=request) response = self.handle_uncaught_exception(request, resolver, sys.exc_info()) </pre><p> Which delivers the error signal to the various handlers (database transaction resets, things like Sentry etc). However, the code that dispatches signals aborts the dispatch if any of the handlers fail (to try..except block): </p> <pre class="wiki"> for receiver in self._live_receivers(_make_id(sender)): response = receiver(signal=self, sender=sender, **named) responses.append((receiver, response)) return responses </pre><p> This is perfectly reasonable in most cases, but is problematic when dealing with top-level error handling, as this prevents the unhandled error from reaching handlers that just want to report it. </p> <p> This is very noticeable in cases where "something bad" happens to the database connection, as the first handler is always the database rollback handler, which only catches DatabaseError, which excludes a lot of errors that can and do crop up in production </p> <pre class="wiki">def _rollback_on_exception(**kwargs): from django.db import transaction for conn in connections: try: transaction.rollback_unless_managed(using=conn) except DatabaseError: pass </pre><p> I think that it will be better to have the error signal dispatcher defer except raising until after all the handlers were called (or just swallow them all). Alternatively, a different signal for error reporting is possible, but I think that's a little confusing. </p> <p> Thoughts? </p> Results #25458: Cookie parse error with wrong django.contrib.message Thu, 24 Sep 2015 11:50:59 GMT maciej-pawlisz <p> I am using Django CMS and BrowserSync and after some action in admin I have the following Cookie header: </p> <pre class="wiki">django_language=en; messages=8702c54129af91621524927d13d81146d5e2d409$[[\"__json_message\"\0540\05425\054\"stron\\u0119 \\\"Czego uczymy\\\" dodany pomy\\u015blnie.\"]]; sessionid=p5t47jhl24n5jks53a40sks2hhxdsot1; csrftoken=h976zQTkIMW9QhWWBAvwhC8q3xpgJ7s5 </pre><p> Unfortunately Django does not parse it correctly: </p> <pre class="wiki">In [4]: cookie.parse_cookie('django_language=en; messages=8702c54129af9162152492 7d13d81146d5e2d409$[[\"__json_message\"\0540\05425\054\"stron\"]]; sessionid=p5t 47jhl24n5jks53a40sks2hhxdsot1; csrftoken=h976zQTkIMW9QhWWBAvwhC8q3xpgJ7s5') Out[4]: {'django_language': 'en'} </pre><p> As you can imagine sessions stop working, because parsing stops after first error. Parse error is actually caused by BrowserSync (it does not send double quotes around message, I filed a bug report about that <a class="ext-link" href=""><span class="icon">​</span></a>). Unfortunately Django is not able to recover from that error, and this wrong cookie stays forever so you cannot log in, or send POST request to a website. </p> <p> Everything works fine when I delete <tt>messages</tt> from the cookie: </p> <pre class="wiki">In [5]: cookie.parse_cookie('django_language=en; sessionid=p5t47jhl24n5jks53a40s ks2hhxdsot1; csrftoken=h976zQTkIMW9QhWWBAvwhC8q3xpgJ7s5') Out[5]: {'csrftoken': 'h976zQTkIMW9QhWWBAvwhC8q3xpgJ7s5', 'django_language': 'en', 'sessionid': 'p5t47jhl24n5jks53a40sks2hhxdsot1'} </pre><p> My Python version is 2.7.10. </p> Results #6727: django.utils.cache.patch_cache_control enhancement when response has empty cache control header Thu, 06 Mar 2008 08:38:47 GMT pascal@… <p> See source:/django/trunk/django/utils/ : </p> <pre class="wiki">60: if response.has_header('Cache-Control'): 61: cc = cc_delim_re.split(response['Cache-Control']) 62: cc = dict([dictitem(el) for el in cc]) </pre><p> If a Cache-Control header exists but is empty, this will add a useless comma in the result. See: </p> <pre class="wiki">&gt;&gt;&gt; cache_control_header='' &gt;&gt;&gt; import re &gt;&gt;&gt; cc_delim_re = re.compile(r'\s*,\s*') &gt;&gt;&gt; cc = cc_delim_re.split(cache_control_header) &gt;&gt;&gt; def dictitem(s): ... t = s.split('=',1) ... if len(t) &gt; 1: ... return (t[0].lower(), t[1]) ... else: ... return (t[0].lower(), True) ... &gt;&gt;&gt; cc = dict([dictitem(el) for el in cc]) &gt;&gt;&gt; cc {'': True} &gt;&gt;&gt; def dictvalue(t): ... if t[1] is True: ... return t[0] ... else: ... return t[0] + '=' + smart_str(t[1]) ... &gt;&gt;&gt; from django.utils.encoding import smart_str &gt;&gt;&gt; cc['max-age']='300' &gt;&gt;&gt; cc = ', '.join([dictvalue(el) for el in cc.items()]) &gt;&gt;&gt; cc ', max-age=300' </pre><p> Note that this is still a valid cache control header according to: </p> <ul><li><a class="ext-link" href=""><span class="icon">​</span></a> </li><li><a class="ext-link" href=""><span class="icon">​</span></a> </li></ul><p> But It would be nicer to test if existing cache control response header is empty, so something like: </p> <pre class="wiki">60: if response.has_header('Cache-Control') and response['Cache-Control']: </pre> Results #17133: get_script_name goofs when there is Apache URL rewriting Fri, 28 Oct 2011 22:34:41 GMT gjanee@… <p> When running under Apache+mod_wsgi (I'm not sure the mod_wsgi is relevant here), using a WSGIScriptAlias of <tt>/foo</tt>, a request for URL <tt>/foo/bar//baz</tt> (note double slash) gets transformed by Apache to <tt>/foo/bar/baz</tt> and then by Django to <tt>/foo//bar/baz</tt> (note where double slashes are now). Furthermore, a callback function for urlpattern <tt>"^bar/.*"</tt> will be called on this latter path even though it doesn't match the pattern. That is, request.path will be <tt>/foo//bar/baz</tt>, which can be confusing for a callback function that is expecting request.path to match the WSGIScriptAlias plus the urlpattern. </p> <p> I don't totally understand what Django is doing here, but I believe the problem is in django.core.handlers.base.get_script_name. In that function, to get the script name in this situation Django starts with the environment variable SCRIPT_URL, and strips off a number of characters at the end equal to the length of environment variable PATH_INFO. Because in this case Apache collapses the double slash in <tt>/foo/bar//baz</tt> to <tt>/foo/bar/baz</tt>, get_script_name strips off one less character than necessary, so that instead of the script name being <tt>/foo</tt> it is <tt>/foo/</tt>. This may account for the double slash appearing <tt>/foo</tt>, as in <tt>/foo//bar/baz</tt>. </p> Results #21777: Make request exception handling more robust to subsequent exceptions Mon, 13 Jan 2014 19:19:36 GMT patrakov@… <p> In django/core/handlers/, there is the following piece of code: </p> <blockquote> <p> except: # Handle everything else. </p> <blockquote> <p> # Get the exception info now, in case another exception is thrown later. signals.got_request_exception.send(sender=self.<span class="underline">class</span>, request=request) response = self.handle_uncaught_exception(request, resolver, sys.exc_info()) </p> </blockquote> </blockquote> <p> Contrary to the comment, the exception info is saved too late. If, during the got_request_exception signal handling another exception occurs (and gets ignored), it will overwrite, and this subsequent exception will get logged, instead of the original one. </p> <p> I hit this while playing with MySQL's SSCursor (for exporting a lot of data to CSV). Some exception happened in my application, then Django's default got_request_exception handler kicked in and attempted to rollback. This failed with a <a class="wiki" href="">ProgrammingError</a>, because not all rows were consumed, and this <a class="wiki" href="">ProgrammingError</a> went into the traceback e-mail instead of the original exception. </p> Results #5897: Add Content-Length header in common middleware Thu, 08 Nov 2007 12:25:09 GMT Scott Barr <scott@…> <p> I've modified to add a "Content-Length" header to the HTTP response if the response code is 200 and the "Content-Length" header hasn't already been supplied. </p> Results #9249: Google Analytics' Cookies break CacheMiddleware when SessionMiddleware turns on Vary: Cookie Tue, 30 Sep 2008 02:55:17 GMT pixelcort <p> When using Google Analytics on a Django project with CacheMiddleware and SessionMiddleware turned on, the Cookies that Google Analytics apparently change on each reload, invalidating the Vary: Cookie parameter that SessionMiddleware is setting. </p> <p> There should be a way to define cookie prefixes, such as <tt></tt>'<span class="underline">utm'<tt></tt>, to ignore for cookie variation for caching. </span></p> Results #10554: Response.set_cookie should allow setting two cookies of the same name. Thu, 19 Mar 2009 20:16:34 GMT jdunck <p> Since cookies have domain and path properties, this is a sensible thing to do: </p> <pre class="wiki">response.set_cookie('x', path='/foo/', expires=&lt;some expired date&gt;) response.set_cookie('x', path='/bar/', expires=&lt;some future date&gt;) </pre><p> It'd be nice if Django allowed this. Sadly, I think this would mean moving away from Cookie. </p> Results #12075: Add wsgiorg.routing args support Thu, 22 Oct 2009 16:06:12 GMT Gustavo <p> The <a class="ext-link" href=""><span class="icon">​</span>wsgiorg.routing_args</a> standard may be really useful if you want to use WSGI middleware or applications inside Django because some of them take advantage of that to do nice/useful things. </p> <p> It's currently not supported in Django - But it will with the attached patch. </p> <p> <em>[edit] fixed broken link.</em> </p> Results #12091: Support for WSGI applications within Django Mon, 26 Oct 2009 17:42:30 GMT Gustavo <p> With the attached patch, it will be possible to run WSGI applications from Django and even use such applications as Django views. </p> <p> It depends on the patch I supplied in <a class="closed ticket" href="" title="New feature: Make Request proxy the WSGI environ (closed: wontfix)">#8927</a>. </p> <p> Please let me know what you think about it. </p> Results #15727: Add support for Content-Security-Policy (CSP) to core Thu, 31 Mar 2011 13:16:57 GMT… <p> out of the box support for CSP would totally rock! See <a class="ext-link" href=""><span class="icon">​</span></a> for more information on what CSP is about. </p> Results #16470: RFC6266 Support Fri, 15 Jul 2011 13:12:22 GMT mnot@… <p> RFC6266, recently published by the IETF HTTPbis WG, describes a way to use the Content-Disposition header in HTTP in a manner whereby almost all current browsers can handle files (e.g., downloading with disposition 'attachment') that have non-ASCII characters in them, with other browsers using an ASCII fallback. </p> <p> Django currently does not have an API for setting Content-Disposition, although there are a few references to it in the documentation. Adding such an API would allow Django sites to download files in any language easily. </p> <p> Additionally, there's advice in the RFC that, properly implemented in a Django API, would help sites avoid common pitfalls. </p> <p> For more information, see: </p> <blockquote> <p> <a class="ext-link" href=""><span class="icon">​</span></a> </p> </blockquote> Results #18855: persist a socket across reloads of the dev server Sat, 25 Aug 2012 15:45:33 GMT dlamotte <p> Using livereload ( with Django becomes painful when updating a file immediately results in reloading the webpage AND the Django dev server. There is a short period of time when the dev server is not listening as it is busy reloading (frequently hit when using livereload). </p> <p> This is exacerbated with larger projects as reload time is longer. </p> <p> This has been an itch I've wanted to scratch for a long time. Hopefully, this will be accepted so others can benefit from it also. Helps plenty even with users hitting Reload manually on their browser. </p> Results #20034: Upload handlers provide no way to retrieve previously parsed POST variables Wed, 13 Mar 2013 01:54:29 GMT rfkrocktk@… <p> In a custom Django upload handler like the one here, it is impossible to get other POST variables sent along with the multipart request until the handler has completed the upload entirely. Often, it'd be nice to be able to grab the variables as they're parsed to do something with them. Essentially, a method should be added to django.core.files.uploadhandler.FileUploadHandler called something like "variable_complete" which would provide the name and content type of each non-file variable passed with the multipart request: </p> <pre class="wiki">class FileUploadHandler: # ... def variable_complete(self, variable_name, variable_value): """ Called after a POST variable has been successfully parsed from the multipart request. """ pass </pre><p> This would save me the trouble of manually having to parse the multipart request myself in "handle_raw_input". </p> Results #20147: Provide an alternative to request.META for accessing HTTP headers Wed, 27 Mar 2013 12:37:47 GMT lukeplant <p> From the docs: </p> <blockquote class="citation"> <p> <tt>HttpRequest.META</tt> A standard Python dictionary containing all available HTTP headers... </p> <p> With the exception of CONTENT_LENGTH and CONTENT_TYPE, as given above, any HTTP headers in the request are converted to META keys by converting all characters to uppercase, replacing any hyphens with underscores and adding an HTTP_ prefix to the name. So, for example, a header called X-Bender would be mapped to the META key HTTP_X_BENDER. </p> </blockquote> <p> The question is, why? Why do we have this ridiculous transform? It is pure silliness, whose only explanation is a quirk of CGI, which is now totally irrelevant. </p> <p> You should be able to look up a header in the HTTP spec and do something very simple to get it from the HTTP request. How about this API: </p> <pre class="wiki">request.HEADERS['Host'] </pre><p> (for consistency with GET/POST/FILES etc.), or even </p> <pre class="wiki">request['Host'] </pre><p> Dictionary access should obey HTTP rules about case-sensitivity of the header names. </p> <p> This also would has the advantage that <tt>repr(request)</tt> wouldn't have lots of junk you don't need i.e. the entire content of <tt>os.environ</tt>, which, on a developer machine especially, can have a <strong>lot</strong> of noise (mine does). </p> <p> It also future-proofs us for when WSGI is replaced with something more sensible, and the whole silly round trip to <tt>os.environ</tt> can be removed completely, or if we want to support something else parallel to WSGI and client code wants to access HTTP headers in the same way for both. </p> <p> This leaves a few things in META that are not derived from an HTTP header, and do not have a way of accessing them from the request object. I think these are just: </p> <ul><li>SCRIPT_NAME - this is a CGI leftover, that is only useful in constructing other things, AFAICS </li><li>QUERY_STRING - this can be easily constructed from <tt>request.get_full_path()</tt> for the rare times that you need the raw query string rather than request.GET </li><li>SERVER_NAME - should use get_host() instead </li><li>SERVER_PORT - use get_host() </li><li>SERVER_PROTOCOL - could use is_secure(), but perhaps it would be nice to have a convenience <tt>get_protocol()</tt> method. </li></ul><p> (see <a class="ext-link" href=""><span class="icon">​</span></a>) </p> Results #21231: Limiting the number of variables and files that a POST request can contain Sat, 05 Oct 2013 12:41:45 GMT epandurski@… <h2 id="TheProblem">The Problem</h2> <p> When deploying a django application one should be able to asses what will be *the absolute maximum* of memory consumed by each serving process/thread. Failing to make this assessment correctly may leave the application open to denial-of-service attacks. For example, when deploying with apache, an excessive number of threads should be available in order protect yourself from slowloris-type attacks. Also, in order to limit the maximum memory and CPU usage under attack "LimitRequestBody" should be set to a reasonably small value (1MB for example). So, here are the naive math: <em>"100 parallel requests"</em> X <em>"1MB per request"</em> = <em>"100MB maximum memory consumed"</em> </p> <p> The problem is that the naive math is wrong. A single 1MB POST request may require *much* more that 1MB to process. 1MB of "application/x-www-form-urlencoded" type may contain 200,000 short name-value pairs, which when fetched into the interpreter consume tens of megabytes (depending on the platform, probably 10-50MB). So the correct math would be: <em>"100 parallel requests"</em> X <em>"50MB per request"</em> = <em>"5000MB maximum memory consumed"</em>. Probably too much for many systems. </p> <p> As far as I know, django does not offer an easy way to protect against such edge cases (lots of simultaneous malicious POST request that consume unexpected amounts of memory). </p> <h2 id="Theproposal">The proposal</h2> <p> Introduce two new settings, limiting the maximum number of entities in a POST request: </p> <p> <strong>FORM_DATA_URLENCODED_MAX_VARS</strong>: the maximum number of name-value pairs in the case of "application/x-www-form-urlencoded". (no limit by default) </p> <p> <strong>FORM_DATA_MULTIPART_MAX_PARTS</strong>: the maximum number of parts in the case of "multipart/form-data". (no limit by default) </p> <p> In case those limits are exceeded, the request must be discarded without being fetched/parsed into memory. (In our example, it would consume only 1MB instead of 50.) </p> Results #21442: Configurable request parsing. Fri, 15 Nov 2013 14:19:05 GMT tomchristie <p> This ticket if for implementing a request parsing API that ensures the <tt>Request</tt> objects can nicely handle JSON and other submitted types in addition the the existing multipart parsing. </p> <p> The proposed API is based on this discussion: <a class="ext-link" href="!searchin/django-developers/request.DATA/django-developers/s8OZ9yNh-8c/oCbNL5x6avAJ"><span class="icon">​</span>!searchin/django-developers/request.DATA/django-developers/s8OZ9yNh-8c/oCbNL5x6avAJ</a> </p> <ul><li><tt>request.DATA</tt> or <tt></tt> for accessing the parsed data. </li><li><tt>request.parsers</tt> or similar for modifying the parsers prior to parsing on a per-view basis. </li><li><tt>request.accepted_parser</tt> or similar for branching on media type if needed. </li><li>A setting <tt>REQUEST_PARSERS</tt> or similar, that controls the default set of installed parsers. </li></ul> Results #22479: Support byte range requests in django.views.static.serve Mon, 21 Apr 2014 03:17:11 GMT slurms <p> As supported by this google groups discussions: <a class="ext-link" href=""><span class="icon">​</span></a> </p> Results #24213: RFC 2231 Section 4.1 is not implemented Sat, 24 Jan 2015 12:27:37 GMT raulcd <p> Currently RFC 2231 Section 4 is implemented (there is an open PR from me for a fix), but section 4.1 of the RFC is not implemented: <a class="ext-link" href=""><span class="icon">​</span></a> Section 4.1 is about being able to have parameter continuation when combining Character Set and language Language headers: </p> <pre class="wiki"> Content-Type: application/x-stuff title*0*=us-ascii'en'This%20is%20even%20more%20 title*1*=%2A%2A%2Afun%2A%2A%2A%20 title*2="isn't it!" </pre> Results