Description
Actual Behavior
Hello,
I am trying to Implement an API,
The API Takes a file as input in a REST API using multipart/form
I am using Flask to implement the REST API and following is the flask script
#!/usr/bin/python3
"""Test server."""
import os
import random
from flask import Flask, request, jsonify
from openapi_core.contrib.flask.decorators import FlaskOpenAPIViewDecorator
from openapi_core import Spec
SPEC = "file_reader.yaml"
openapi = FlaskOpenAPIViewDecorator.from_spec(Spec.from_file_path(SPEC))
app = Flask(__name__)
def __save_file_locally(file_object:object) -> str:
if file_object.filename:
filepath = os.path.join("/tmp/", f"{file_object.filename}.{random.randint(1,100)}")
if os.path.exists(filepath):
os.unlink(filepath)
file_object.save(filepath)
return filepath
return None
@app.route("/test", methods=["POST"])
@openapi
def read_permission():
"""Test function"""
# print(f"request OpenAPI dir : {request.openapi.body.items()}")
__save_file_locally(request.files['inputFile'])
return jsonify({"key": "Value"})
if __name__ == "__main__":
app.run(host="0.0.0.0", port=567, debug=True)
# curl -X POST -H "Content-type: application/json" --data '{"flag":"ttF"}' http://localhost:567/test
and following is the file_reader.yaml file
openapi: '3.0.2'
info:
title: Test Title
version: '1.0'
servers:
- url: http://localhost:567/
paths:
/test:
post:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
inputFile:
type: string
format: binary
responses:
200:
description: Sample response
content:
application/json:
schema:
type: object
properties:
key:
type: string
minLength: 6
maxLength: 20
# curl -X POST -H "Content-type: multipart/form-data" -F "file=@file_reader.py" http://localhost:567/test
However when I hit the API I get following validation error
root@ip-10-31-1-221:~/openapi_core_POC# curl -X POST -H "Content-type: multipart/form-data" -F "file=@file_reader.py" http://localhost:567/test | python3 -m json.tool
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2884 100 1588 100 1296 258k 210k --:--:-- --:--:-- --:--:-- 469k
{
"errors": [
{
"class": "<class 'openapi_core.deserializing.media_types.exceptions.MediaTypeDeserializeError'>",
"status": 400,
"title": "Failed to deserialize value with multipart/form-data mimetype: --------------------------2c4bf22387dcbcbc\r\nContent-Disposition: form-data; name=\"file\"; filename=\"file_reader.py\"\r\nContent-Type: application/octet-stream\r\n\r\n#!/usr/bin/python3\n\"\"\"Test server.\"\"\"\n\nimport os\nimport random\nfrom flask import Flask, request, jsonify\nfrom openapi_core.contrib.flask.decorators import FlaskOpenAPIViewDecorator\nfrom openapi_core import Spec\n\nSPEC = \"file_reader.yaml\"\nopenapi = FlaskOpenAPIViewDecorator.from_spec(Spec.from_file_path(SPEC))\n\napp = Flask(__name__)\n\ndef __save_file_locally(file_object:object) -> str:\n if file_object.filename:\n filepath = os.path.join(\"/tmp/\", f\"{file_object.filename}.{random.randint(1,100)}\")\n if os.path.exists(filepath):\n os.unlink(filepath)\n file_object.save(filepath)\n return filepath\n return None\n\n@app.route(\"/test\", methods=[\"POST\"])\n@openapi\ndef read_permission():\n \"\"\"Test function\"\"\"\n # print(f\"request OpenAPI dir : {request.openapi.body.items()}\")\n __save_file_locally(request.files['inputFile'])\n return jsonify({\"key\": \"Value\"})\n\nif __name__ == \"__main__\":\n app.run(host=\"0.0.0.0\", port=567, debug=True)\n\n # curl -X POST -H \"Content-type: application/json\" --data '{\"flag\":\"ttF\"}' http://localhost:567/test\n\r\n--------------------------2c4bf22387dcbcbc--\r\n"
}
]
}
Expected Behavior
It is expected that there should be no validation errors as we have specified mime type as multipart/form.
Also as per OpenAPI docs, OpenAPI 3.0 does not support type:file
field,
and as per docs, while taking input we should specify type:string
and format:binary
so just wanted to confirm whether the request body is correct or not
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
inputFile:
type: string
format: binary
Steps to Reproduce
Write the provided python3 file as file_reader.py
and provided yaml file as file_reader.yaml
Execute file_reader.py file
and use following CURL command to make a request
curl -X POST -H "Content-type: multipart/form-data" -F "file=@file_reader.py" http://localhost:567/test
OpenAPI Core Version
0.17.1
OpenAPI Core Integration
Flask
Affected Area(s)
Deserializing
References
No response
Anything else we need to know?
No response
Would you like to implement a fix?
Yes