예제 #1
0
def _get_requested_range(request: Request) -> Optional[Range]:
    # http://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7233.html#rfc.section.3.1
    # A server must ignore a Range header field received with a request method
    # other than GET
    if request.method != "GET":
        return None

    # NB: only the first Range request header is taken into consideration;
    # if the HTTP contains several Range headers, only the first is used
    range_header = request.get_first_header(b"range")

    if not range_header:
        return None

    try:
        value = Range.parse(range_header)
    except InvalidRangeValue:
        raise BadRequest("Invalid Range header")
    else:
        # An origin server must ignore a Range header field that contains
        # a range unit it does not understand.
        if value.unit != "bytes":
            return None

        return value
예제 #2
0
 async def example_2():
     # example: use an exception to control the execution flow,
     # the error handler defined in app.exceptions_handlers will produce the
     # response object
     # the response object must be populated with CORS headers, otherwise the
     # client won't expose the error details - for example we might send a JSON
     # structure with error information
     raise BadRequest("Some user friendly client error detail")
예제 #3
0
 def converter(data):
     try:
         return expected_type(**data)
     except TypeError as type_error:
         raise BadRequest(
             f"invalid parameter in request payload, " +
             f"caused by type {_try_get_type_name(expected_type)} or " +
             "one of its subproperties. Error: " +
             _generalize_init_type_error_message(type_error))
예제 #4
0
def _default_bool_converter(value: str) -> bool:
    if value in {"1", "true"}:
        return True

    if value in {"0", "false"}:
        return False

    # bad request: expected a bool value, but
    # got something different that is not handled
    raise BadRequest(f"Expected a bool value for a parameter, but got {value}.")
예제 #5
0
def _default_bool_converter(value: str):
    if value in {'1', 'true'}:
        return True

    if value in {'0', 'false'}:
        return False

    # bad request: expected a bool value, but
    # got something different that is not handled
    raise BadRequest()
예제 #6
0
def parse_value(value, desired_type: type, param_name: str):
    try:
        if desired_type is bool:
            return bool(int(value))
        if desired_type in {int, float}:
            return desired_type(value)
        return value
    except ValueError:
        raise BadRequest(
            f'invalid parameter "{param_name}". '
            f'The value cannot be parsed as {desired_type.__name__}.')
예제 #7
0
    def __call__(self, request):
        value = get_param(request, self.name)

        if value is None or value == '':
            if self.is_optional:
                return None

            raise BadRequest(f'missing parameter: {self.name}.')

        if self.annotation is str:
            return unwrap(value)

        return value
예제 #8
0
    async def file_chunker() -> AsyncIterable[bytes]:
        async with files_handler.open(file_path) as file:
            for part in range_option:
                if part.start is None and part.end is None:
                    raise BadRequest("Invalid range part: both boundaries are None")
                if part.start is not None and part.end is not None:
                    # return a portion between start and end indexes
                    await file.seek(part.start, 0)
                    part_size = part.end - part.start

                elif part.end is None:
                    assert part.start is not None
                    # return all bytes to the end, starting from start index
                    await file.seek(part.start)
                    part_size = file_size - part.start

                elif part.start is None:
                    # return a number of units at the end of the file
                    await file.seek(file_size - part.end)
                    part_size = part.end

                bytes_to_return = part_size

                while True:
                    chunk_limit = (
                        size_limit if bytes_to_return > size_limit else bytes_to_return
                    )
                    chunk = await file.read(chunk_limit)

                    if not chunk:
                        break

                    bytes_to_return -= len(chunk)

                    if boundary:
                        yield b"--" + boundary + b"\r\n"
                        yield b"Content-Type: " + file_type + b"\r\n"
                        yield b"Content-Range: " + _get_content_range_value(
                            part, file_size
                        ) + b"\r\n\r\n"

                    yield chunk

                    if boundary:
                        yield b"\r\n"

        if boundary:
            yield b"--" + boundary + b"--\r\n"

        yield b""
예제 #9
0
    async def get_value(self, request: Request) -> T:
        raw_value = self.get_raw_value(request)
        try:
            value = self.converter(raw_value)
        except (ValueError, BadRequest):
            raise BadRequest(
                f'Invalid value for parameter `{self.name}`; expected {self.expected_type}'
            )

        if value is None and self.required:
            raise MissingParameterError(self.name, self.source_name)

        if not self.required and self._empty_iterable(value):
            return None

        return value
예제 #10
0
    async def get_value(self, request: Request) -> Optional[T]:
        # TODO: support get_raw_value returning None, to not instantiate lists
        # when a parameter is not present
        raw_value = self.get_raw_value(request)
        try:
            value = self.converter(raw_value)
        except (ValueError, BadRequest):
            raise BadRequest(
                f"Invalid value {raw_value} for parameter `{self.parameter_name}`; "
                f"expected a valid {self.expected_type.__name__}."
            )

        if self.default is not empty and (value is None or self._empty_iterable(value)):
            return None

        if value is None and self.required and self.root_required:
            raise MissingParameterError(self.parameter_name, self.source_name)

        if not self.required and self._empty_iterable(value):
            return None

        return value