python-restx / flask-restx

Fork of Flask-RESTPlus: Fully featured framework for fast, easy and documented API development with Flask
https://flask-restx.readthedocs.io/en/latest/
Other
2.17k stars 337 forks source link

@api.expect decorator does not validate DateTime fields #344

Open thomsentner opened 3 years ago

thomsentner commented 3 years ago

Code

import json

import requests
from flask import Flask, request
from flask_restx import Api, Resource, fields
from jsonschema import FormatChecker

app = Flask(__name__)
api_restplus = Api(
    app,
    # format_checker=FormatChecker(formats=("date",)),
)

myApi_arguments_fields = api_restplus.model("payload", {"begin_date": fields.Date()})

@api_restplus.route("/myApi")
class MyApi(Resource):
    @api_restplus.expect(myApi_arguments_fields, validate=True)
    def post(self):
        _ = json.loads(request.data)
        return None

if __name__ == "__main__":
    app.run(port=5001)

Repro Steps

Execute:

% curl -X POST "http://127.0.0.1:5001/myApi" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"begin_date\":\"test\"}

Expected Behavior

I would expect the following response:

{"errors": {"begin_date": "'test' is not a 'date'"}, "message": "Input payload validation failed"}

Actual Behavior

Even though the begin_date does not conform iso8601 format, I don't get a validation error. The input passes validation just fine.

Environment

Additional Context

The bug is fixable by uncommenting the following line in my code example:

    # format_checker=FormatChecker(formats=("date",)),

An issue about this bug has been open at Flask-RESTPlus since 2016: noirbizarre/flask-restplus#204.

I feel like this is a bug, as having a fields.Date functionality implies that validation will take place, but it actually doesn't. This behavior seems to be sort-of documented, but its documentation is extremely tucked away and not explicit, and this whole problem gave me quite a headache. I feel like either the FormatChecker functionality should be turned on by default, a warning / exception should be raised if no FormatChecker is provided but flask_restx.fields.Date is initiated, or at least flask_restx.fields.Date / flask_restx.fields.DateTime's documentation should be improved.

nathalieGG commented 1 year ago

Also, the api.payload doesn't match the model definition. Date fields a rendered as String and not as Date

Melkaz commented 8 months ago

Same for me :(

I'm currently using a simple regex but it's very flimsy as it can't validate all the iso8601 patterns:

iso8601_regex = r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$'

model = api.model('Model', {
    'timepoint': fields.String(required=True, description='Timepoint in ISO 8601 format', pattern=iso8601_regex),
    # Other fields...
})