Example #1
0
    def range(self):
        try:
            value = self.env['HTTP_RANGE']
            if '=' in value:
                unit, sep, req_range = value.partition('=')
            else:
                msg = "The value must be prefixed with a range unit, e.g. 'bytes='"
                raise errors.HTTPInvalidHeader(msg, 'Range')
        except KeyError:
            return None

        if ',' in req_range:
            msg = 'The value must be a continuous range.'
            raise errors.HTTPInvalidHeader(msg, 'Range')

        try:
            first, sep, last = req_range.partition('-')

            if not sep:
                raise ValueError()

            if first:
                return (int(first), int(last or -1))
            elif last:
                return (-int(last), -1)
            else:
                msg = 'The range offsets are missing.'
                raise errors.HTTPInvalidHeader(msg, 'Range')

        except ValueError:
            href = 'http://goo.gl/zZ6Ey'
            href_text = 'HTTP/1.1 Range Requests'
            msg = ('It must be a range formatted according to RFC 7233.')
            raise errors.HTTPInvalidHeader(msg, 'Range', href=href,
                                           href_text=href_text)
Example #2
0
    def content_length(self):
        try:
            value = self.env['CONTENT_LENGTH']
        except KeyError:
            return None

        # NOTE(kgriffs): Normalize an empty value to behave as if
        # the header were not included; wsgiref, at least, inserts
        # an empty CONTENT_LENGTH value if the request does not
        # set the header. Gunicorn and uWSGI do not do this, but
        # others might if they are trying to match wsgiref's
        # behavior too closely.
        if not value:
            return None

        try:
            value_as_int = int(value)
        except ValueError:
            msg = 'The value of the header must be a number.'
            raise errors.HTTPInvalidHeader(msg, 'Content-Length')

        if value_as_int < 0:
            msg = 'The value of the header must be a positive number.'
            raise errors.HTTPInvalidHeader(msg, 'Content-Length')

        return value_as_int
Example #3
0
    def _deserialize_form(
        self, stream, content_type, content_length, form_cls=MultipartForm
    ):
        if not form_cls:
            raise NotImplementedError

        _, options = cgi.parse_header(content_type)
        try:
            boundary = options['boundary']
        except KeyError:
            raise errors.HTTPInvalidHeader(
                'No boundary specifier found in {!r}'.format(content_type),
                'Content-Type',
            )

        # NOTE(vytas): RFC 2046, section 5.1.
        #   If a boundary delimiter line appears to end with white space, the
        #   white space must be presumed to have been added by a gateway, and
        #   must be deleted.
        boundary = boundary.rstrip()

        # NOTE(vytas): RFC 2046, section 5.1.
        #   The boundary parameter consists of 1 to 70 characters from a set of
        #   characters known to be very robust through mail gateways, and NOT
        #   ending with white space.
        if not 1 <= len(boundary) <= 70:
            raise errors.HTTPInvalidHeader(
                'The boundary parameter must consist of 1 to 70 characters',
                'Content-Type',
            )

        return form_cls(stream, boundary.encode(), content_length, self.parse_options)
Example #4
0
    def content_length(self):
        try:
            value = self._asgi_headers[b'content-length']
        except KeyError:
            return None

        try:
            # PERF(vytas): int() also works with a bytestring argument.
            value_as_int = int(value)
        except ValueError:
            # PERF(vytas): Check for an empty value in the except clause,
            #   because we do not expect ASGI servers to inject any headers
            #   that the client did not provide.

            # NOTE(kgriffs): Normalize an empty value to behave as if
            # the header were not included; wsgiref, at least, inserts
            # an empty CONTENT_LENGTH value if the request does not
            # set the header. Gunicorn and uWSGI do not do this, but
            # others might if they are trying to match wsgiref's
            # behavior too closely.
            if not value:
                return None

            msg = 'The value of the header must be a number.'
            raise errors.HTTPInvalidHeader(msg, 'Content-Length')

        if value_as_int < 0:
            msg = 'The value of the header must be a positive number.'
            raise errors.HTTPInvalidHeader(msg, 'Content-Length')

        return value_as_int
Example #5
0
    def get_header_as_datetime(self, header, required=False, obs_date=False):
        """Return an HTTP header with HTTP-Date values as a datetime.

        Args:
            name (str): Header name, case-insensitive (e.g., 'Date')
            required (bool, optional): Set to ``True`` to raise
                ``HTTPBadRequest`` instead of returning gracefully when the
                header is not found (default ``False``).
            obs_date (bool, optional): Support obs-date formats according to
                RFC 7231, e.g.: "Sunday, 06-Nov-94 08:49:37 GMT"
                (default ``False``).

        Returns:
            datetime: The value of the specified header if it exists,
            or ``None`` if the header is not found and is not required.

        Raises:
            HTTPBadRequest: The header was not found in the request, but
                it was required.
            HttpInvalidHeader: The header contained a malformed/invalid value.
        """

        try:
            http_date = self.get_header(header, required=required)
            return util.http_date_to_dt(http_date, obs_date=obs_date)
        except TypeError:
            # When the header does not exist and isn't required
            return None
        except ValueError:
            msg = ('It must be formatted according to RFC 7231, '
                   'Section 7.1.1.1')
            raise errors.HTTPInvalidHeader(msg, header)
Example #6
0
    def range_unit(self):
        try:
            value = self.env['HTTP_RANGE']

            if '=' in value:
                unit, sep, req_range = value.partition('=')
                return unit
            else:
                msg = "The value must be prefixed with a range unit, e.g. 'bytes='"
                raise errors.HTTPInvalidHeader(msg, 'Range')
        except KeyError:
            return None