Hi Luke,
On 04/08/2013 02:02 PM, Luke Plant wrote:
> This is already the subject of a ticket, but I didn't get a response
> yet. Basically, the idea is replace things like:
>
> request.META['HTTP_ACCEPT']
>
> with
>
> request.HEADERS['Accept']
>
> request.META should be deprecated and replaced with request._META,
> because it is just an implementation detail, and a really bizarre one at
> that, full of cruft from a previous generation of web applications (CGI)
> that should not be exposed in our API.
I have no problem with providing a nicer API for getting at request
headers that allows asking for un-mangled header names, but I don't
think we should deprecate request.META (or turn it into a private
implementation detail).
Although the concept of a unified "request environ" that includes HTTP
headers mashed together with various other environment and web server
info may date back to CGI, it is not outdated; in fact it is a part of
the WSGI specification too:
http://www.python.org/dev/peps/pep-3333/#environ-variables
I think the WSGI environ should always remain accessible through public
API on a Django request object.
> Anything else needed from META should also be replaced with a sensible API.
I'm not sure how you envision this happening, since there is no fixed
set of things that might be "needed from META" that we can provide
purpose-specific API for. It is a legitimate use of WSGI for people to
set arbitrary environ variables from their WSGI server and expect to be
able to read those variables from Django, and they shouldn't have to use
private API to do this.
> This might seem to be a big change simply for the sake of a clean API,
> but I'm more and more motivated by these thoughts:
>
> * Web development is hard enough as it is. "Explain this to a newbie
> without getting embarrassed" is a good test.
Sure; if we introduce a new API for getting at HTTP headers sans
name-mangling, I think it'd be fine to consider request.META "advanced
API" and adjust the documentation accordingly to make it much less
prominent.
> There is also the advantage of a *much* cleaner repr(request),
> especially in a development environment, because you don't have all the
> other junk from os.environ.
If we are trying to make repr(request) really be a full reproduction of
all relevant request data (such that the request instance could be fully
reconstructed from it) then I don't think this goal is achievable; it is
not an option (IMO) to remove WSGI environ data from the request
entirely, because this would make data that is part of the WSGI spec
inaccessible to Django users.
(I haven't checked whether the current repr(request) meets the
full-reconstruction criteria; if it already doesn't then I don't really
care what we show in it, we could trim it down further with or without
your proposed change.)
> The biggest problem is what to do with our test Client and
> RequestFactory, which allow specifying headers as keyword arguments
> using the CGI style of naming e.g.:
>
> self.client.get('/path', HTTP_X_REQUESTED_WITH='XMLHttpRequest')
>
> Since keyword arguments can't have "-" in them, this is harder to
> replace. We could either leave it as it is, or add a new 'headers'
> keyword argument to these methods, deprecating **extra.
Similar to above, I think we could add a new "headers" arg for
friendlier specification of HTTP headers, but I don't think we should
deprecate **extra. (This of course would mean we have to decide and
document which takes precedence if they conflict.)
> The silliness has infected other places, like SECURE_PROXY_SSL_HEADER
> which follows the same CGI convention (and in each case the docs have to
> note how to do it correctly!). In this case we can detect people using
> the old style 'HTTP_' and raise a deprecation warning, and allow the
> sensible way.
There might be cases where people are using an environ var rather than
an HTTP header to indicate proxied SSL, and currently
SECURE_PROXY_SSL_HEADER works fine this way (despite the HEADER in the
name). That said, I can't immediately find any current prominent
documents recommending this or situations where using a HTTP header
instead wouldn't be workable. Unless someone comes up with such a
situation, and given that both the name of the setting and its
documentation only discuss its use with headers, I think I'd be ok
deprecating its use with non-headers and moving to friendlier header names.
> We would probably also need to add a few methods/attributes to
> HttpRequest to proxy the few things you need from request.META that are
> not headers, like REMOTE_ADDRESS and REMOTE_USER
As I mentioned above, I don't think we can dictate the "few things you
need from request.META" and make the rest inaccessible.
> Is anyone strongly opposed to this? If not, in Aymeric's spirit of
> decisiveness, I'll push it forward.
I'm fine with new request.headers API; I'm opposed to deprecation of
request.META.
Carl