Example #1
0
    def require_params(self, req):
        """
        Require all parameters from request that are defined for this resource.

        Raises ``falcon.errors.HTTPMissingParam`` exception if any of required
        parameters is missing and ``falcon.errors.HTTPInvalidParam`` if any
        of parameters could not be understood (wrong format).

        Args:
            req (falcon.Request): request object

        """
        # TODO: handle specifying parameter multiple times in query string!
        params = {}

        for name, param in self.params.items():
            if name not in req.params and param.required:
                # we could simply raise with this single param or use get_param
                # with required=True parameter but for client convenience
                # we prefer to list all missing params that are required
                missing = set(
                    p for p in self.params if self.params[p].required) - set(
                        req.params.keys())

                raise errors.HTTPMissingParam(", ".join(missing))

            elif name in req.params or param.default:
                # Note: lack of key in req.params means it was not specified
                # so unless there is default value it will not be included in
                # output params dict.
                # This way we have explicit information that param was
                # not specified. Using None would not be as good because param
                # class can also return None from `.value()` method as a valid
                # translated value.
                try:
                    if param.many:
                        # params with "many" enabled need special care
                        params[name] = req.get_param_as_list(
                            name,
                            param.value,
                        ) or [param.default and param.value(param.default)]
                    else:
                        # note that if many==False and query parameter
                        # occurs multiple times in qs then it is
                        # **unspecified** which one will be used. See:
                        # http://falcon.readthedocs.org/en/latest/api/request_and_response.html#falcon.Request.get_param  # noqa
                        params[name] = param.value(
                            req.get_param(name, default=param.default))

                except ValueError as err:
                    raise errors.HTTPInvalidParam(str(err), name)

        return params
Example #2
0
    def get_param_as_date(self,
                          name,
                          format_string='%Y-%m-%d',
                          required=False,
                          store=None):
        """Return the value of a query string parameter as a date.

        Args:
            name (str): Parameter name, case-sensitive (e.g., 'ids').
            format_string (str): String used to parse the param value into a
                date.
                Any format recognized by strptime() is supported.
                (default ``"%Y-%m-%d"``)
            required (bool, optional): Set to ``True`` to raise
                ``HTTPBadRequest`` instead of returning ``None`` when the
                parameter is not found (default ``False``).
            store (dict, optional): A ``dict``-like object in which to place
                the value of the param, but only if the param is found (default
                ``None``).
        Returns:
            datetime.date: The value of the param if it is found and can be
                converted to a ``date`` according to the supplied format
                string. If the param is not found, returns ``None`` unless
                required is ``True``.

        Raises:
            HTTPBadRequest: A required param is missing from the request.
            HTTPInvalidParam: A transform function raised an instance of
                ``ValueError``.
        """

        param_value = self.get_param(name, required=required)

        if param_value is None:
            return None

        try:
            date = strptime(param_value, format_string).date()
        except ValueError:
            msg = 'The date value does not match the required format.'
            raise errors.HTTPInvalidParam(msg, name)

        if store is not None:
            store[name] = date

        return date
Example #3
0
    def get_param_as_dict(self, name, required=False, store=None):
        """Return the value of a query string parameter as a dict.

        Given a JSON value, parse and return it as a dict.

        Args:
            name (str): Parameter name, case-sensitive (e.g., 'payload').
            required (bool, optional): Set to ``True`` to raise
                ``HTTPBadRequest`` instead of returning ``None`` when the
                parameter is not found (default ``False``).
            store (dict, optional): A ``dict``-like object in which to place
                the value of the param, but only if the param is found (default
                ``None``).

        Returns:
            dict: The value of the param if it is found. Otherwise, returns
            ``None`` unless required is ``True``.

        Raises:
            HTTPBadRequest: A required param is missing from the request.
            HTTPInvalidParam: The parameter's value could not be parsed as JSON.
        """

        param_value = self.get_param(name, required=required)

        if param_value is None:
            return None

        try:
            val = json.loads(param_value)
        except ValueError:
            msg = 'It could not be parsed as JSON.'
            raise errors.HTTPInvalidParam(msg, name)

        if store is not None:
            store[name] = val

        return val
Example #4
0
    def get_param_as_bool(self, name, required=False, store=None,
                          blank_as_true=False):
        """Return the value of a query string parameter as a boolean

        The following boolean strings are supported::

            TRUE_STRINGS = ('true', 'True', 'yes', '1')
            FALSE_STRINGS = ('false', 'False', 'no', '0')

        Args:
            name (str): Parameter name, case-sensitive (e.g., 'detailed').
            required (bool, optional): Set to ``True`` to raise
                ``HTTPBadRequest`` instead of returning ``None`` when the
                parameter is not found or is not a recognized boolean
                string (default ``False``).
            store (dict, optional): A ``dict``-like object in which to place
                the value of the param, but only if the param is found (default
                ``None``).
            blank_as_true (bool): If ``True``, an empty string value will be
                treated as ``True``. Normally empty strings are ignored; if
                you would like to recognize such parameters, you must set the
                `keep_blank_qs_values` request option to ``True``. Request
                options are set globally for each instance of ``falcon.API``
                through the `req_options` attribute.

        Returns:
            bool: The value of the param if it is found and can be converted
            to a ``bool``. If the param is not found, returns ``None``
            unless required is ``True``.

        Raises:
            HTTPBadRequest: A required param is missing from the request.

        """

        params = self._params

        # PERF: Use if..in since it is a good all-around performer; we don't
        #       know how likely params are to be specified by clients.
        if name in params:
            val = params[name]
            if isinstance(val, list):
                val = val[-1]

            if val in TRUE_STRINGS:
                val = True
            elif val in FALSE_STRINGS:
                val = False
            elif blank_as_true and not val:
                val = True
            else:
                msg = 'The value of the parameter must be "true" or "false".'
                raise errors.HTTPInvalidParam(msg, name)

            if store is not None:
                store[name] = val

            return val

        if not required:
            return None

        raise errors.HTTPMissingParam(name)
Example #5
0
    def get_param_as_int(self, name,
                         required=False, min=None, max=None, store=None):
        """Return the value of a query string parameter as an int.

        Args:
            name (str): Parameter name, case-sensitive (e.g., 'limit').
            required (bool, optional): Set to ``True`` to raise
                ``HTTPBadRequest`` instead of returning ``None`` when the
                parameter is not found or is not an integer (default
                ``False``).
            min (int, optional): Set to the minimum value allowed for this
                param. If the param is found and it is less than min, an
                ``HTTPError`` is raised.
            max (int, optional): Set to the maximum value allowed for this
                param. If the param is found and its value is greater than
                max, an ``HTTPError`` is raised.
            store (dict, optional): A ``dict``-like object in which to place
                the value of the param, but only if the param is found
                (default ``None``).

        Returns:
            int: The value of the param if it is found and can be converted to
            an integer. If the param is not found, returns ``None``, unless
            `required` is ``True``.

        Raises
            HTTPBadRequest: The param was not found in the request, even though
                it was required to be there. Also raised if the param's value
                falls outside the given interval, i.e., the value must be in
                the interval: min <= value <= max to avoid triggering an error.

        """

        params = self._params

        # PERF: Use if..in since it is a good all-around performer; we don't
        #       know how likely params are to be specified by clients.
        if name in params:
            val = params[name]
            if isinstance(val, list):
                val = val[-1]

            try:
                val = int(val)
            except ValueError:
                msg = 'The value must be an integer.'
                raise errors.HTTPInvalidParam(msg, name)

            if min is not None and val < min:
                msg = 'The value must be at least ' + str(min)
                raise errors.HTTPInvalidParam(msg, name)

            if max is not None and max < val:
                msg = 'The value may not exceed ' + str(max)
                raise errors.HTTPInvalidParam(msg, name)

            if store is not None:
                store[name] = val

            return val

        if not required:
            return None

        raise errors.HTTPMissingParam(name)
Example #6
0
    def get_param_as_list(self, name,
                          transform=None, required=False, store=None):
        """Return the value of a query string parameter as a list.

        List items must be comma-separated or must be provided
        as multiple instances of the same param in the query string
        ala *application/x-www-form-urlencoded*.

        Args:
            name (str): Parameter name, case-sensitive (e.g., 'ids').
            transform (callable, optional): An optional transform function
                that takes as input each element in the list as a ``str`` and
                outputs a transformed element for inclusion in the list that
                will be returned. For example, passing ``int`` will
                transform list items into numbers.
            required (bool, optional): Set to ``True`` to raise
                ``HTTPBadRequest`` instead of returning ``None`` when the
                parameter is not found (default ``False``).
            store (dict, optional): A ``dict``-like object in which to place
                the value of the param, but only if the param is found (default
                ``None``).

        Returns:
            list: The value of the param if it is found. Otherwise, returns
            ``None`` unless required is True. Empty list elements will be
            discarded. For example, the following query strings would
            both result in `['1', '3']`::

                things=1,,3
                things=1&things=&things=3

        Raises:
            HTTPBadRequest: A required param is missing from the request.
            HTTPInvalidParam: A transform function raised an instance of
                ``ValueError``.

        """

        params = self._params

        # PERF: Use if..in since it is a good all-around performer; we don't
        #       know how likely params are to be specified by clients.
        if name in params:
            items = params[name]

            # NOTE(warsaw): When a key appears multiple times in the request
            # query, it will already be represented internally as a list.
            # NOTE(kgriffs): Likewise for comma-delimited values.
            if not isinstance(items, list):
                items = [items]

            # PERF(kgriffs): Use if-else rather than a DRY approach
            # that sets transform to a passthrough function; avoids
            # function calling overhead.
            if transform is not None:
                try:
                    items = [transform(i) for i in items]

                except ValueError:
                    msg = 'The value is not formatted correctly.'
                    raise errors.HTTPInvalidParam(msg, name)

            if store is not None:
                store[name] = items

            return items

        if not required:
            return None

        raise errors.HTTPMissingParam(name)