Skip to content

Commit

Permalink
validate date-time format
Browse files Browse the repository at this point in the history
  • Loading branch information
hjacobs committed Jul 20, 2015
1 parent 8051ad7 commit 5e5cff6
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 1 deletion.
25 changes: 25 additions & 0 deletions connexion/decorators/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
language governing permissions and limitations under the License.
"""

import datetime
import flask
import functools
import logging
Expand All @@ -29,6 +30,21 @@
'boolean': bool} # map of swagger types to python types


def parse_datetime(s: str):
'''http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'''
try:
# "Z" for UTC
datetime.datetime.strptime(s, '%Y-%m-%dT%H:%M:%S.%fZ')
except:
# "+02:00" time zone offset
# remove the ":" first (%z expects "+0200")
x = s[:-3] + s[-2:]
datetime.datetime.strptime(x, '%Y-%m-%dT%H:%M:%S.%f%z')


FORMAT_MAP = {('string', 'date-time'): parse_datetime}


class RequestBodyValidator:
def __init__(self, schema):
self.schema = schema
Expand Down Expand Up @@ -92,3 +108,12 @@ def validate_schema(self, data, schema) -> flask.Response:
logger.error("'%s' is not a '%s'", data, expected_type_name)
return problem(400, 'Bad Request',
"Wrong type, expected '{}' got '{}'".format(schema_type, actual_type_name))

schema_format = schema.get('format')
func = FORMAT_MAP.get((schema_type, schema_format))
if func:
try:
func(data)
except:
return problem(400, 'Bad Request',
"Invalid value, expected {} in '{}' format".format(schema_type, schema_format))
21 changes: 20 additions & 1 deletion tests/fakeapi/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,25 @@ paths:
description: goodbye response
schema:
type: string
/test_schema_format:
post:
summary: Returns empty response
description: Returns empty response
operationId: fakeapi.hello.schema_format
parameters:
- name: timestamp
required: true
in: body
schema:
type: string
format: date-time
produces:
- application/json
responses:
200:
description: goodbye response
schema:
type: string
/test_not_implemented:
post:
summary: Returns empty response
Expand All @@ -241,4 +260,4 @@ definitions:
type: string
description: Docker image version to deploy
required:
- image_version
- image_version
4 changes: 4 additions & 0 deletions tests/fakeapi/hello.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ def schema():

def schema_list():
return ''


def schema_format():
return ''
13 changes: 13 additions & 0 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,16 @@ def test_schema_list(app):
wrong_items_response = json.loads(wrong_items.data.decode()) # type: dict
assert wrong_items_response['title'] == 'Bad Request'
assert wrong_items_response['detail'] == "Wrong type, expected 'string' got 'int'"


def test_schema_format(app):
app_client = app.app.test_client()
headers = {'Content-type': 'application/json'}

wrong_type = app_client.post('/v1.0/test_schema_format', headers=headers, data=json.dumps("xy")) # type: flask.Response
assert wrong_type.status_code == 400
assert wrong_type.content_type == 'application/problem+json'
wrong_type_response = json.loads(wrong_type.data.decode()) # type: dict
assert wrong_type_response['title'] == 'Bad Request'
assert wrong_type_response['detail'] == "Invalid value, expected string in 'date-time' format"

0 comments on commit 5e5cff6

Please sign in to comment.