Skip to content
Danila Ganchar edited this page Jan 24, 2021 · 39 revisions

How to use

v4 example


from flask import Flask, jsonify

from flask_request_validator import *
from flask_request_validator.error_formatter import demo_error_formatter
from flask_request_validator.exceptions import InvalidRequestError, InvalidHeadersError, RuleError

app = Flask(__name__)
@app.errorhandler(InvalidRequestError)
def data_error(e):
    # customize error messages as you wish
    # Attention! We do not support demo_error_formatter. Demo is just a demo. Feel free to suggest a new formatter
    return jsonify(demo_error_formatter(e))


@app.errorhandler(InvalidHeadersError)
def header_error(e):
    # customize error messages as you wish
    return jsonify(demo_error_formatter(e))

# how to use custom rules
class MyCustomRule(AbstractRule):
    def validate(self, value: str) -> str:
        # do something...
        if value != 'ok':
            # or raise ListRuleError(['error1', 'error2', 'error3'])
            raise RuleError('invalid header')
        return value


@app.route('/json/<string:uid>', methods=['POST'])
@validate_params(
    Param('Authorization', HEADER, str, rules=[MyCustomRule()]),
    Param('colors', GET, list),
    Param('values', GET, dict),
    Param('uid', PATH, str, rules=CompositeRule(MinLength(3), MaxLength(5))),
    Param('dt', JSON, str, rules=[Datetime('%Y-%m-%d %H:%M:%S')]),
    Param('status', JSON, str, rules=[Enum('active', 'inactive')]),
    Param('name', JSON, str, rules=[Pattern(r'^[a-z]{4,20}$')]),
)
def json(valid: ValidRequest, uid):
    json_data = valid.get_json()
    json_data['dt'] = json_data['dt'].strftime('%Y-%m-%d')
    return jsonify({
        'get': valid.get_params(),
        'json': json_data,
        'path': valid.get_path_params(),
    })

Headers validation works first:

curl --header "Content-Type: application/json" --request POST --data '{}' \
  http://localhost:5000/json/good?colors=green,yellow,blue&values=field1:val1,field2:val2
#["invalid header Authorization. value is required"]

curl --header "Content-Type: application/json" \
  --header "Authorization: invalid" --request POST --data '{}' \
  http://localhost:5000/json/very_long?colors=green,yellow,blue&values=field1:val1,field2:val2
#["invalid header Authorization. invalid header"]

All other parameters are checked when all headers are correct:

curl --header "Content-Type: application/json" \
  --header "Authorization: ok" --request POST --data '{}' \
  http://localhost:5000/json/very_long?colors=green,yellow,blue&values=field1:val1,field2:val2
# result
[
  {
    "errors": {
      "dt": "value is required",
      "name": "value is required",
      "status": "value is required"
    },
    "message": "invalid JSON parameters"
  },
  {
    "errors": {
      "uid": "invalid length, max length = 5"
    },
    "message": "invalid PATH parameters"
  }
]

One more invalid request:

curl --header "Content-Type: application/json" \
--header "Authorization: ok" --request POST \
--data '{"name":"bad","status":"undefined","dt":"2020-01-02 03:04:"}' \
http://localhost:5000/json/very_long?colors=green,yellow,blue&values=field1:val1,field2:val2
# result
[
  {
    "errors": {
      "dt": "expected a datetime in %Y-%m-%d %H:%M:%S format",
      "name": "value does not match pattern ^[a-z]{4,20}$",
      "status": "not allowed, allowed values: active|inactive"
    },
    "message": "invalid JSON parameters"
  },
  {
    "errors": {
      "uid": "invalid length, max length = 5"
    },
    "message": "invalid PATH parameters"
  }
]

Correct request:

curl --header "Content-Type: application/json" \
--header "Authorization: ok" --request POST \
--data '{"name":"test","status":"active","dt":"2020-01-02 03:04:05"}' \
http://localhost:5000/json/good?colors=green,yellow,blue&values=field1:val1,field2:val2

Param description:

Param(
    name: the name of the request parameter
    param_type: where stored param(GET, FORM, JSON, PATH, HEADER)
    value_type: str, bool, int, float, dict, list - which type we want to have
    required: a bool that indicates whether a value is required, True by default
    default: the default value, None by default. You can use lambda for this arg - default=lambda: ['test']
    rule: the list of rules (see class Rule)
)

Note!(you can see in the example above)

  • bool should be sent from client as: 1, 0, or true / false in any register
  • list should be sent from client as value1,value2,value3
  • dict should be sent from client as key1:val1,key2:val2

Other details:

Clone this wiki locally