def make_action(self, fn, schema_parser, meta):
        """
        Make resource's method an action

        Validate input, output by schema in meta.
        If no input schema, call fn without params.
        If no output schema, will not validate return value.

        Args:
            fn: resource's method
            schema_parser: for parsing schema in meta
            meta: meta data of the action
        """
        validate_input = validate_output = None
        if "$input" in meta:
            with MarkKey("$input"):
                validate_input = schema_parser.parse(meta["$input"])
        if "$output" in meta:
            with MarkKey("$output"):
                validate_output = schema_parser.parse(meta["$output"])

        def action(data):
            if validate_input:
                try:
                    data = validate_input(data)
                except Invalid as ex:
                    return abort(400, "InvalidData", str(ex))
                if isinstance(data, dict):
                    rv = fn(**data)
                else:
                    rv = fn(data)
            else:
                rv = fn()
            rv, status, headers = unpack(rv)
            if validate_output:
                try:
                    rv = validate_output(rv)
                except Invalid as ex:
                    return abort(500, "ServerError", str(ex))
            return rv, status, headers
        return action
Make resource's method an action

        Validate input, output by schema in meta.
        If no input schema, call fn without params.
        If no output schema, will not validate return value.

        Args:
            fn: resource's method
            schema_parser: for parsing schema in meta
            meta: meta data of the action