spec-first / connexion

Connexion is a modern Python web framework that makes spec-first and api-first development easy.
https://connexion.readthedocs.io/en/latest/
Apache License 2.0
4.49k stars 764 forks source link

Date format parameter not validated #476

Closed chimeno closed 2 years ago

chimeno commented 7 years ago

Description

When defining an endpoint with a parameter in the date format, is not validated.

Expected behaviour

Should return 400 status code.

Actual behaviour

The code function is executed.

Steps to reproduce

  1. Define an endpoint like:

    
    get:
      operationId: business_kpi.get_summary
      summary: Retrieves the summary of kpis for month
      parameters:
        - $ref: '#/parameters/date'
        - $ref: '#/parameters/comp_date'
      responses:
     ...
    
    date:
    name: date
    description: Date to query kpis
    in: query
    required: true
    type: string
    format: date


2. Make a request with an invalid date (ej. 123)

### Additional info:

Output of the commands:

- python 3.6.1
- 1.1.9 and 1.1.10
rafaelcaricio commented 7 years ago

We have removed this because the code which implements date/time validation is not compatible with Apache license.

You can activate this validation for your application by installing pip install strict-rfc3339>=0.6. Please keep in mind that the library "strict-rfc3339" is under GPLv3. You can read more on this topic in https://github.com/zalando/connexion/pull/404.

rafaelcaricio commented 7 years ago

@chimeno Please close this issue if that answer your question.

chimeno commented 7 years ago

Well, after installing pip install strict-rfc3339>=0.6, date-time format is working but date format it does not work. Indeed there is a log: ValueError: time data '12----' does not match format '%Y-%m-%d' but not error is raised.

rafaelcaricio commented 7 years ago

Could you send the full stack trace? Impossible to help just with this line. :)

chimeno commented 7 years ago

Yep, for sure:

[2017-06-30 09:23:44,521] ERROR in app: Exception on /api/v0.5.0/kpis/summary [GET]
Traceback (most recent call last):
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/connexion/decorators/decorator.py", line 66, in wrapper
    response = function(request)
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/connexion/decorators/validation.py", line 293, in wrapper
    return function(request)
  File "/Users/daniel.chimeno/Documents/projects/venv-api/lib/python3.6/site-packages/connexion/decorators/response.py", line 85, in wrapper
    response = function(request)
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/connexion/decorators/decorator.py", line 42, in wrapper
    response = function(request)
  File "/Users/a/Documents/projects/venv-api/lib/python3.6/site-packages/connexion/decorators/parameter.py", line 195, in wrapper
    return function(**kwargs)
  File "/Users/a/Documents/projects/analytics-smartcomms/api/src/business_kpi.py", line 149, in get_summary
    comp_date = previous_month(date, 1)
  File "/Users/a/Documents/projects/analytics-smartcomms/api/src/utils/date.py", line 60, in previous_month
    curr = datetime.strptime(day, "%Y-%m-%d")
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_strptime.py", line 565, in _strptime_datetime
    tt, fraction = _strptime(data_string, format)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_strptime.py", line 362, in _strptime
    (data_string, format))
ValueError: time data '12----' does not match format '%Y-%m-%d'
2017-06-30;09:23:44;utils.logging;INFO;{'message': 'Ending FPA request', 'path': '/api/v0.5.0/kpis/summary', 'method': 'GET', 'authorization': '', 'status_code': 500, 'response': '{  "detail": "The server encountered an internal error and was unable to complete your request.  Either the server is overloaded or there is an error in the application.",  "status": 500,  "title": "Internal Server Error",  "type": "about:blank"}'}
2017-06-30;09:23:44;tornado.access;ERROR;500 GET /api/v0.5.0/kpis/summary?date=12---- (127.0.0.1) 5.34ms

This happens with strict-rfc3339>=0.6 installed or not. Edit: I've just realized the ValueError is raised by the function code, and not by the params validator.

chimeno commented 7 years ago

It is possible to workaround this by creating a custom format:

@draft4_format_checker.checks('customdate')
def is_custom_date(val):
    from datetime import datetime
    try:
        _ = datetime.strptime(val, '%Y-%m-%d')
    except ValueError:
        return False
    return True
rafaelcaricio commented 7 years ago

Cool! Thanks for posting your solution. Maybe now we can close this issue?

chimeno commented 7 years ago

Yes, we can close, but there is still an issue regarding dates and datetimes... Feel free to close it. Thanks!

rafaelcaricio commented 7 years ago

What is the issue regarding dates and datetimes?

chimeno commented 7 years ago

date format is not validating although strict-rfc3339 is installed.

rafaelcaricio commented 7 years ago

Ok, I will investigate this later. I will leave this open for now then.

rafaelcaricio commented 7 years ago

@chimeno Could you please post a snippet of your OpenAPI spec with the datetime format parameter?

chimeno commented 7 years ago

Relevant spec:

swagger: '2.0'
info:
  title: xxx
  version: "123"
basePath: '/api/v0.5.0'
consumes:
  - application/json
produces:
  - application/json
paths:
  /kpis/summary:
    get:
      operationId: business_kpi.get_summary
      summary: Retrieves the summary of kpis for month
      parameters:
        - $ref: '#/parameters/date'
        - $ref: '#/parameters/comp_date'
      responses:
        200:
          description: Successful response.
          schema:
            type: array
            minItems: 0
            items:
              $ref: '#/definitions/KpiData'
        401:
          description: Not authorized
        404:
          description: Content not found

######### PARAMETERS DEFINITION
parameters:

  date:
    name: date
    description: Date to query kpis
    in: query
    required: true
    type: string
    format: date

  comp_date:
    name: comp_date
    description: KPI comparation date
    in: query
    required: false
    type: string
    format: date
Weilor commented 5 years ago

Is there any progress about this issue? I installed strict-rfc3339 but date-format param is still be validated. @rafaelcaricio

worldmind commented 5 years ago

Minimal example it works fine: cat openapi.yaml

openapi: 3.0.2
info:
  title: Test date
  version: 4.0.0

servers:
  - url: /4

paths:
  /alerts:
    post:
      summary: Post a new alerts
      operationId: api.post_alerts

      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Date'

      responses:
        '200':
          description: OK

components:
  schemas:
    Date:
      type: object
      properties:
        date:
          type: string
          format: date-time

cat ex.json {"date": "sjkahdfkasjhdk"} run

$ http POST localhost:8080/4/alerts < ex.json                                                                    
HTTP/1.0 400 BAD REQUEST
Content-Length: 124
Content-Type: application/problem+json
Date: Fri, 24 May 2019 08:20:22 GMT
Server: Werkzeug/0.15.4 Python/3.6.7

{
    "detail": "'sjkahdfkasjhdk' is not a 'date-time'",
    "status": 400,
    "title": "Bad Request",
    "type": "about:blank"
}
worldmind commented 5 years ago

As I understood it is require strict-rfc3339 module that not installs automatically from connexion deps.

mik-laj commented 4 years ago

I found a solution under the MIT license. https://github.com/Julian/jsonschema/blob/9d5edb4749ab1f6194aa5c7c099c6e6fd402c4cf/jsonschema/_format.py#L305-L324 We can install the rfc3339_validator library (MIT), which is a fallback for strict-rfc3339 (GPL).

RobbeSneyders commented 2 years ago

This can be done using jsonschema.

mattixpet commented 2 years ago

Just in case this helps anyone in my shoes, I was trying to use date-time format of strings and have it validated through request body, but Connexion just wasn't validating it, so I came across this thread. However, installing strict-rfc3339>=0.6 like suggested did not work. However, installing rfc3339-validator worked like a charm.