def _wrap_stream(self): # pragma nocover try: content_length = self.content_length or 0 except HTTPInvalidHeader: # NOTE(kgriffs): The content-length header was specified, # but it had an invalid value. Assume no content. content_length = 0 self.stream = helpers.Body(self.stream, content_length)
def _wrap_stream(self): # pragma nocover try: # NOTE(kgriffs): We can only add the wrapper if the # content-length header was provided. if self.content_length is not None: self.stream = helpers.Body(self.stream, self.content_length) except HTTPInvalidHeader: # NOTE(kgriffs): The content-length header was specified, # but it had an invalid value. pass
def _wrap_stream(self): try: content_length = self.content_length or 0 # NOTE(kgriffs): This branch is indeed covered in test_wsgi.py # even though coverage isn't able to detect it. except errors.HTTPInvalidHeader: # pragma: no cover # NOTE(kgriffs): The content-length header was specified, # but it had an invalid value. Assume no content. content_length = 0 self.stream = helpers.Body(self.stream, content_length)
def __init__(self, env): """Initialize attributes based on a WSGI environment dict Note: Request is not meant to be instantiated directory by responders. Args: env: A WSGI environment dict passed in from the server. See also the PEP-3333 spec. """ self.env = env self._wsgierrors = env['wsgi.errors'] self.stream = env['wsgi.input'] self.method = env['REQUEST_METHOD'] # Normalize path path = env['PATH_INFO'] if path: if len(path) != 1 and path.endswith('/'): self.path = path[:-1] else: self.path = path else: self.path = '/' # QUERY_STRING isn't required to be in env, so let's check # PERF: if...in is faster than using env.get(...) if 'QUERY_STRING' in env: self.query_string = env['QUERY_STRING'] else: self.query_string = '' # PERF: Don't parse it if we don't have to! if self.query_string: self._params = helpers.parse_query_string(self.query_string) else: self._params = {} self._headers = helpers.parse_headers(env) # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust, # normalizing semantics between, e.g., gunicorn and wsgiref. if isinstance(self.stream, NativeStream): # pragma: nocover # NOTE(kgriffs): coverage can't detect that this *is* actually # covered since the test that does so uses multiprocessing. self.stream = helpers.Body(self.stream, self.content_length)
def test_body_stream_wrapper(self): data = testing.rand_string(SIZE_1_KB / 2, SIZE_1_KB) expected_body = data.encode('utf-8') expected_len = len(expected_body) # NOTE(kgriffs): Append newline char to each line # to match readlines behavior expected_lines = [(line + '\n').encode('utf-8') for line in data.split('\n')] # NOTE(kgriffs): Remove trailing newline to simulate # what readlines does expected_lines[-1] = expected_lines[-1][:-1] stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) self.assertEquals(body.read(), expected_body) stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) self.assertEquals(body.read(2), expected_body[0:2]) stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) self.assertEquals(body.read(expected_len + 1), expected_body) stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) self.assertEquals(body.readline(), expected_lines[0]) stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) self.assertEquals(body.readlines(), expected_lines) stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) self.assertEquals(next(body), expected_lines[0]) stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) for i, line in enumerate(body): self.assertEquals(line, expected_lines[i])
def test_body_stream_wrapper(self): data = testing.rand_string(SIZE_1_KB / 2, SIZE_1_KB) expected_body = data.encode('utf-8') expected_len = len(expected_body) # NOTE(kgriffs): Append newline char to each line # to match readlines behavior expected_lines = [(line + '\n').encode('utf-8') for line in data.split('\n')] # NOTE(kgriffs): Remove trailing newline to simulate # what readlines does expected_lines[-1] = expected_lines[-1][:-1] stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.read() == expected_body stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.read(2) == expected_body[0:2] stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.read(expected_len + 1) == expected_body # NOTE(kgriffs): Test that reading past the end does not # hang, but returns the empty string. stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) for i in range(expected_len + 1): expected_value = expected_body[i:i + 1] if i < expected_len else b'' assert body.read(1) == expected_value stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.readline() == expected_lines[0] stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.readline(-1) == expected_lines[0] stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.readline(expected_len + 1) == expected_lines[0] stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.readlines() == expected_lines stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.readlines(-1) == expected_lines stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert body.readlines(expected_len + 1) == expected_lines stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) assert next(body) == expected_lines[0] stream = io.BytesIO(expected_body) body = request_helpers.Body(stream, expected_len) for i, line in enumerate(body): assert line == expected_lines[i]
def __init__(self, env): self.env = env if self.context_type is None: # Literal syntax is more efficient than using dict() self.context = {} else: # pylint will detect this as not-callable because it only sees the # declaration of None, not whatever type a subclass may have set. self.context = self.context_type() # pylint: disable=not-callable self._wsgierrors = env['wsgi.errors'] self.stream = env['wsgi.input'] self.method = env['REQUEST_METHOD'] # Normalize path path = env['PATH_INFO'] if path: if len(path) != 1 and path.endswith('/'): self.path = path[:-1] else: self.path = path else: self.path = '/' # QUERY_STRING isn't required to be in env, so let's check # PERF: if...in is faster than using env.get(...) if 'QUERY_STRING' in env and env['QUERY_STRING']: # TODO(kgriffs): Should this escape individual values instead # of the entire string? The way it is now, this: # # x=ab%2Bcd%3D42%2C9 # # becomes this: # # x=ab+cd=42,9 # self.query_string = uri.decode(env['QUERY_STRING']) else: self.query_string = six.text_type() # PERF: Don't parse it if we don't have to! if self.query_string: self._params = uri.parse_query_string(self.query_string) else: self._params = {} helpers.normalize_headers(env) self._cached_headers = {} self._cached_uri = None self._cached_relative_uri = None self.content_type = self._get_header_by_wsgi_name('HTTP_CONTENT_TYPE') # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust, # normalizing semantics between, e.g., gunicorn and wsgiref. if isinstance(self.stream, NativeStream): # pragma: nocover # NOTE(kgriffs): coverage can't detect that this *is* actually # covered since the test that does so uses multiprocessing. self.stream = helpers.Body(self.stream, self.content_length) # PERF(kgriffs): Technically, we should spend a few more # cycles and parse the content type for real, but # this heuristic will work virtually all the time. if (self.content_type and 'application/x-www-form-urlencoded' in self.content_type): # NOTE(kgriffs): This assumes self.stream has been patched # above in the case of wsgiref, so that self.content_length # is not needed. Normally we just avoid accessing # self.content_length, because it is a little expensive # to call. We could cache self.content_length, but the # overhead to do that won't usually be helpful, since # content length will only ever be read once per # request in most cases. body = self.stream.read() body = body.decode('ascii') extra_params = uri.parse_query_string(uri.decode(body)) self._params.update(extra_params)
def __init__(self, env): """Initialize attributes based on a WSGI environment dict Note: Request is not meant to be instantiated directory by responders. Args: env: A WSGI environment dict passed in from the server. See also the PEP-3333 spec. """ self.env = env self._wsgierrors = env['wsgi.errors'] self.stream = env['wsgi.input'] self.method = env['REQUEST_METHOD'] # Normalize path path = env['PATH_INFO'] if path: if len(path) != 1 and path.endswith('/'): self.path = path[:-1] else: self.path = path else: self.path = '/' # QUERY_STRING isn't required to be in env, so let's check # PERF: if...in is faster than using env.get(...) if 'QUERY_STRING' in env and env['QUERY_STRING']: # TODO(kgriffs): Should this escape individual values instead # of the entire string? The way it is now, this: # # x=ab%2Bcd%3D42%2C9 # # becomes this: # # x=ab+cd=42,9 # self.query_string = uri.decode(env['QUERY_STRING']) else: self.query_string = six.text_type() # PERF: Don't parse it if we don't have to! if self.query_string: self._params = uri.parse_query_string(self.query_string) else: self._params = {} helpers.normalize_headers(env) self._cached_headers = {} self._cached_uri = None self._cached_relative_uri = None # NOTE(kgriffs): Wrap wsgi.input if needed to make read() more robust, # normalizing semantics between, e.g., gunicorn and wsgiref. if isinstance(self.stream, NativeStream): # pragma: nocover # NOTE(kgriffs): coverage can't detect that this *is* actually # covered since the test that does so uses multiprocessing. self.stream = helpers.Body(self.stream, self.content_length)