diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py index bb02cb08ace7..5fbc3a70ab7e 100644 --- a/django/contrib/admin/sites.py +++ b/django/contrib/admin/sites.py @@ -323,7 +323,7 @@ def each_context(self, request): For sites running on a subpath, use the SCRIPT_NAME value if site_url hasn't been customized. """ - script_name = request.META["SCRIPT_NAME"] + script_name = request.meta["SCRIPT_NAME"] site_url = ( script_name if self.site_url == "/" and script_name else self.site_url ) diff --git a/django/contrib/admindocs/middleware.py b/django/contrib/admindocs/middleware.py index 5c9f08d0cc93..14ffd0e67c43 100644 --- a/django/contrib/admindocs/middleware.py +++ b/django/contrib/admindocs/middleware.py @@ -25,7 +25,7 @@ def process_view(self, request, view_func, view_args, view_kwargs): "'django.contrib.auth.middleware.AuthenticationMiddleware'." ) if request.method == "HEAD" and ( - request.META.get("REMOTE_ADDR") in settings.INTERNAL_IPS + request.meta.get("REMOTE_ADDR") in settings.INTERNAL_IPS or (request.user.is_active and request.user.is_staff) ): response = HttpResponse() diff --git a/django/contrib/auth/middleware.py b/django/contrib/auth/middleware.py index 6b8dd4340e9f..4139f606262f 100644 --- a/django/contrib/auth/middleware.py +++ b/django/contrib/auth/middleware.py @@ -49,7 +49,7 @@ class RemoteUserMiddleware(MiddlewareMixin): """ # Name of request header to grab username from. This will be the key as - # used in the request.META dictionary, i.e. the normalization of headers to + # used in the request.meta dictionary, i.e. the normalization of headers to # all uppercase and the addition of "HTTP_" prefix apply. header = "REMOTE_USER" force_logout_if_no_header = True @@ -65,7 +65,7 @@ def process_request(self, request): " before the RemoteUserMiddleware class." ) try: - username = request.META[self.header] + username = request.meta[self.header] except KeyError: # If specified header doesn't exist then remove any existing # authenticated remote-user, or return (leaving request.user set to diff --git a/django/contrib/messages/api.py b/django/contrib/messages/api.py index 7a67e8b4b097..95771dae4b3d 100644 --- a/django/contrib/messages/api.py +++ b/django/contrib/messages/api.py @@ -26,7 +26,7 @@ def add_message(request, level, message, extra_tags="", fail_silently=False): try: messages = request._messages except AttributeError: - if not hasattr(request, "META"): + if not hasattr(request, "meta"): raise TypeError( "add_message() argument must be an HttpRequest object, not " "'%s'." % request.__class__.__name__ diff --git a/django/core/exceptions.py b/django/core/exceptions.py index 2a2288ff4dc9..ca073c0d8e03 100644 --- a/django/core/exceptions.py +++ b/django/core/exceptions.py @@ -60,7 +60,7 @@ class DisallowedRedirect(SuspiciousOperation): class TooManyFieldsSent(SuspiciousOperation): """ - The number of fields in a GET or POST request exceeded + The number of fields in a request.query_params or POST request exceeded settings.DATA_UPLOAD_MAX_NUMBER_FIELDS. """ diff --git a/django/core/files/uploadhandler.py b/django/core/files/uploadhandler.py index b6c185e8fc72..fc0764cff8d1 100644 --- a/django/core/files/uploadhandler.py +++ b/django/core/files/uploadhandler.py @@ -91,7 +91,7 @@ def handle_raw_input( :input_data: An object that supports reading via .read(). :META: - ``request.META``. + ``request.meta``. :content_length: The (integer) value of the Content-Length header from the client. diff --git a/django/core/handlers/asgi.py b/django/core/handlers/asgi.py index 7b0086fb765a..eb4c6c6ca4c0 100644 --- a/django/core/handlers/asgi.py +++ b/django/core/handlers/asgi.py @@ -71,7 +71,7 @@ def __init__(self, scope, body_file): query_string = self.scope.get("query_string", "") if isinstance(query_string, bytes): query_string = query_string.decode() - self.META = { + self.meta = { "REQUEST_METHOD": self.method, "QUERY_STRING": query_string, "SCRIPT_NAME": self.script_name, @@ -81,16 +81,16 @@ def __init__(self, scope, body_file): "wsgi.multiprocess": True, } if self.scope.get("client"): - self.META["REMOTE_ADDR"] = self.scope["client"][0] - self.META["REMOTE_HOST"] = self.META["REMOTE_ADDR"] - self.META["REMOTE_PORT"] = self.scope["client"][1] + self.meta["REMOTE_ADDR"] = self.scope["client"][0] + self.meta["REMOTE_HOST"] = self.meta["REMOTE_ADDR"] + self.meta["REMOTE_PORT"] = self.scope["client"][1] if self.scope.get("server"): - self.META["SERVER_NAME"] = self.scope["server"][0] - self.META["SERVER_PORT"] = str(self.scope["server"][1]) + self.meta["SERVER_NAME"] = self.scope["server"][0] + self.meta["SERVER_PORT"] = str(self.scope["server"][1]) else: - self.META["SERVER_NAME"] = "unknown" - self.META["SERVER_PORT"] = "0" - # Headers go into META. + self.meta["SERVER_NAME"] = "unknown" + self.meta["SERVER_PORT"] = "0" + # Headers go into meta. for name, value in self.scope.get("headers", []): name = name.decode("latin1") if name == "content-length": @@ -102,19 +102,19 @@ def __init__(self, scope, body_file): # HTTP/2 say only ASCII chars are allowed in headers, but decode # latin1 just in case. value = value.decode("latin1") - if corrected_name in self.META: - value = self.META[corrected_name] + "," + value - self.META[corrected_name] = value + if corrected_name in self.meta: + value = self.meta[corrected_name] + "," + value + self.meta[corrected_name] = value # Pull out request encoding, if provided. - self._set_content_type_params(self.META) + self._set_content_type_params(self.meta) # Directly assign the body file to be our stream. self._stream = body_file # Other bits. self.resolver_match = None @cached_property - def GET(self): - return QueryDict(self.META["QUERY_STRING"]) + def query_params(self): + return QueryDict(self.meta["QUERY_STRING"]) def _get_scheme(self): return self.scope.get("scheme") or super()._get_scheme() @@ -137,7 +137,7 @@ def _get_files(self): @cached_property def COOKIES(self): - return parse_cookie(self.META.get("HTTP_COOKIE", "")) + return parse_cookie(self.meta.get("HTTP_COOKIE", "")) def close(self): super().close() diff --git a/django/core/handlers/wsgi.py b/django/core/handlers/wsgi.py index 9324af083ecd..ec99f960cebe 100644 --- a/django/core/handlers/wsgi.py +++ b/django/core/handlers/wsgi.py @@ -65,9 +65,9 @@ def __init__(self, environ): # http://test/something and http://test//something being different as # stated in RFC 3986. self.path = "%s/%s" % (script_name.rstrip("/"), path_info.replace("/", "", 1)) - self.META = environ - self.META["PATH_INFO"] = path_info - self.META["SCRIPT_NAME"] = script_name + self.meta = environ + self.meta["PATH_INFO"] = path_info + self.meta["SCRIPT_NAME"] = script_name self.method = environ["REQUEST_METHOD"].upper() # Set content_type, content_params, and encoding. self._set_content_type_params(environ) @@ -83,7 +83,7 @@ def _get_scheme(self): return self.environ.get("wsgi.url_scheme") @cached_property - def GET(self): + def query_params(self): # The WSGI spec says 'QUERY_STRING' may be absent. raw_query_string = get_bytes_from_wsgi(self.environ, "QUERY_STRING", "") return QueryDict(raw_query_string, encoding=self._encoding) diff --git a/django/http/multipartparser.py b/django/http/multipartparser.py index dfd406c35eac..963f48cdf542 100644 --- a/django/http/multipartparser.py +++ b/django/http/multipartparser.py @@ -54,12 +54,12 @@ class MultiPartParser: boundary_re = _lazy_re_compile(r"[ -~]{0,200}[!-~]") - def __init__(self, META, input_data, upload_handlers, encoding=None): + def __init__(self, meta, input_data, upload_handlers, encoding=None): """ Initialize the MultiPartParser object. - :META: - The standard ``META`` dictionary in Django request objects. + :meta: + The standard ``meta`` dictionary in Django request objects. :input_data: The raw post data, as a file-like object. :upload_handlers: @@ -69,7 +69,7 @@ def __init__(self, META, input_data, upload_handlers, encoding=None): The encoding with which to treat the incoming data. """ # Content-Type should contain multipart and the boundary information. - content_type = META.get("CONTENT_TYPE", "") + content_type = meta.get("CONTENT_TYPE", "") if not content_type.startswith("multipart/"): raise MultiPartParserError("Invalid Content-Type: %s" % content_type) @@ -92,7 +92,7 @@ def __init__(self, META, input_data, upload_handlers, encoding=None): # Content-Length should contain the length of the body we are about # to receive. try: - content_length = int(META.get("CONTENT_LENGTH", 0)) + content_length = int(meta.get("CONTENT_LENGTH", 0)) except (ValueError, TypeError): content_length = 0 @@ -108,7 +108,7 @@ def __init__(self, META, input_data, upload_handlers, encoding=None): possible_sizes = [x.chunk_size for x in upload_handlers if x.chunk_size] self._chunk_size = min([2**31 - 4] + possible_sizes) - self._meta = META + self._meta = meta self._encoding = encoding or settings.DEFAULT_CHARSET self._content_length = content_length self._upload_handlers = upload_handlers @@ -202,7 +202,7 @@ def _parse(self): # last boundary. if settings.DATA_UPLOAD_MAX_NUMBER_FIELDS + 2 < num_post_keys: raise TooManyFieldsSent( - "The number of GET/POST parameters exceeded " + "The number of query_params/POST parameters exceeded " "settings.DATA_UPLOAD_MAX_NUMBER_FIELDS." ) diff --git a/django/http/request.py b/django/http/request.py index fe15a173be58..a074b4311e9a 100644 --- a/django/http/request.py +++ b/django/http/request.py @@ -41,9 +41,9 @@ class UnreadablePostError(OSError): class RawPostDataException(Exception): """ - You cannot access raw_post_data from a request that has + You cannot access raw_post_data from a POST request that has a multipart/* POST data if it has been accessed via POST, - FILES, etc.. + files, etc.. """ pass @@ -52,7 +52,7 @@ class RawPostDataException(Exception): class HttpRequest: """A basic HTTP request.""" - # The encoding used in GET/POST dicts. None means use default setting. + # The encoding used in query_params and POST dicts. None means use default setting. _encoding = None _upload_handlers = [] @@ -61,10 +61,10 @@ def __init__(self): # Any variable assignment made here should also happen in # `WSGIRequest.__init__()`. - self.GET = QueryDict(mutable=True) + self.query_params = QueryDict(mutable=True) self.POST = QueryDict(mutable=True) self.COOKIES = {} - self.META = {} + self.meta = {} self.FILES = MultiValueDict() self.path = "" @@ -85,7 +85,7 @@ def __repr__(self): @cached_property def headers(self): - return HttpHeaders(self.META) + return HttpHeaders(self.meta) @cached_property def accepted_types(self): @@ -116,13 +116,13 @@ def _get_raw_host(self): allowed hosts protection, so may return an insecure host. """ # We try three options, in order of decreasing preference. - if settings.USE_X_FORWARDED_HOST and ("HTTP_X_FORWARDED_HOST" in self.META): - host = self.META["HTTP_X_FORWARDED_HOST"] - elif "HTTP_HOST" in self.META: - host = self.META["HTTP_HOST"] + if settings.USE_X_FORWARDED_HOST and ("HTTP_X_FORWARDED_HOST" in self.meta): + host = self.meta["HTTP_X_FORWARDED_HOST"] + elif "HTTP_HOST" in self.meta: + host = self.meta["HTTP_HOST"] else: # Reconstruct the host using the algorithm from PEP 333. - host = self.META["SERVER_NAME"] + host = self.meta["SERVER_NAME"] server_port = self.get_port() if server_port != ("443" if self.is_secure() else "80"): host = "%s:%s" % (host, server_port) @@ -152,10 +152,10 @@ def get_host(self): def get_port(self): """Return the port number for the request as a string.""" - if settings.USE_X_FORWARDED_PORT and "HTTP_X_FORWARDED_PORT" in self.META: - port = self.META["HTTP_X_FORWARDED_PORT"] + if settings.USE_X_FORWARDED_PORT and "HTTP_X_FORWARDED_PORT" in self.meta: + port = self.meta["HTTP_X_FORWARDED_PORT"] else: - port = self.META["SERVER_PORT"] + port = self.meta["SERVER_PORT"] return str(port) def get_full_path(self, force_append_slash=False): @@ -170,8 +170,8 @@ def _get_full_path(self, path, force_append_slash): return "%s%s%s" % ( escape_uri_path(path), "/" if force_append_slash and not path.endswith("/") else "", - ("?" + iri_to_uri(self.META.get("QUERY_STRING", ""))) - if self.META.get("QUERY_STRING", "") + ("?" + iri_to_uri(self.meta.get("QUERY_STRING", ""))) + if self.meta.get("QUERY_STRING", "") else "", ) @@ -259,7 +259,7 @@ def scheme(self): "The SECURE_PROXY_SSL_HEADER setting must be a tuple containing " "two values." ) - header_value = self.META.get(header) + header_value = self.meta.get(header) if header_value is not None: header_value, *_ = header_value.split(",", 1) return "https" if header_value.strip() == secure_value else "http" @@ -275,13 +275,13 @@ def encoding(self): @encoding.setter def encoding(self, val): """ - Set the encoding used for GET/POST accesses. If the GET or POST - dictionary has already been created, remove and recreate it on the - next access (so that it is decoded correctly). + Set the encoding used for query_params/POST accesses. If the query_params or + POST dictionary has already been created, remove and recreate it on the next + access (so that it is decoded correctly). """ self._encoding = val - if hasattr(self, "GET"): - del self.GET + if hasattr(self, "query_params"): + del self.query_params if hasattr(self, "_post"): del self._post @@ -307,7 +307,7 @@ def upload_handlers(self, upload_handlers): ) self._upload_handlers = upload_handlers - def parse_file_upload(self, META, post_data): + def parse_file_upload(self, meta, post_data): """Return a tuple of (POST QueryDict, FILES MultiValueDict).""" self.upload_handlers = ImmutableList( self.upload_handlers, @@ -316,7 +316,7 @@ def parse_file_upload(self, META, post_data): "processed." ), ) - parser = MultiPartParser(META, post_data, self.upload_handlers, self.encoding) + parser = MultiPartParser(meta, post_data, self.upload_handlers, self.encoding) return parser.parse() @property @@ -330,7 +330,7 @@ def body(self): # Limit the maximum request data size that will be handled in-memory. if ( settings.DATA_UPLOAD_MAX_MEMORY_SIZE is not None - and int(self.META.get("CONTENT_LENGTH") or 0) + and int(self.meta.get("CONTENT_LENGTH") or 0) > settings.DATA_UPLOAD_MAX_MEMORY_SIZE ): raise RequestDataTooBig( @@ -369,7 +369,7 @@ def _load_post_and_files(self): else: data = self try: - self._post, self._files = self.parse_file_upload(self.META, data) + self._post, self._files = self.parse_file_upload(self.meta, data) except (MultiPartParserError, TooManyFilesSent): # An error occurred while parsing POST data. Since when # formatting the error the request handler might access @@ -427,6 +427,38 @@ def __iter__(self): def readlines(self): return list(self) + @property + def GET(self): + return self.query_params + + @GET.setter + def GET(self, value): + self.query_params = value + + @property + def COOKIES(self): + return self.cookies + + @COOKIES.setter + def COOKIES(self, value): + self.cookies = value + + @property + def META(self): + return self.meta + + @META.setter + def META(self, value): + self.meta = value + + @property + def FILES(self): + return self.files + + @FILES.setter + def FILES(self, value): + self.files = value + class HttpHeaders(CaseInsensitiveMapping): HTTP_PREFIX = "HTTP_" @@ -483,7 +515,7 @@ class QueryDict(MultiValueDict): """ A specialized MultiValueDict which represents a query string. - A QueryDict can be used to represent GET or POST data. It subclasses + A QueryDict can be used to represent query_params or POST data. It subclasses MultiValueDict since keys in such data can be repeated, for instance in the data from a form with a