Exemplo n.º 1
0
    def get_param(self, name, required=False, store=None, default=None):
        """Return the raw value of a query string parameter as a string.

        Note:
            If an HTML form is POSTed to the API using the
            *application/x-www-form-urlencoded* media type, the
            parameters from the request body will be merged into
            the query string parameters.

            If a key appears more than once in the form data, one of the
            values will be returned as a string, but it is undefined which
            one. Use `req.get_param_as_list()` to retrieve all the values.

        Note:
            Similar to the way multiple keys in form data is handled,
            if a query parameter is assigned a comma-separated list of
            values (e.g., 'foo=a,b,c'), only one of those values will be
            returned, and it is undefined which one. Use
            `req.get_param_as_list()` to retrieve all the values.

        Args:
            name (str): Parameter name, case-sensitive (e.g., 'sort').
            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 present.
            default (any, optional): If the param is not found returns the
                given value instead of None

        Returns:
            str: The value of the param as a string, or ``None`` if param is
                not found and is not required.

        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:
            # NOTE(warsaw): If the key appeared multiple times, it will be
            # stored internally as a list.  We do not define which one
            # actually gets returned, but let's pick the last one for grins.
            param = params[name]
            if isinstance(param, list):
                param = param[-1]

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

            return param

        if not required:
            return default

        raise errors.HTTPMissingParam(name)
Exemplo n.º 2
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
Exemplo n.º 3
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)
Exemplo n.º 4
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)
Exemplo n.º 5
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)