Repository navigation
Closed
Labels
✨ enhancementNew feature or improvementNew feature or improvement🍭 OpenAPI ComplianceSupporting a new bit of the OpenAPI specSupporting a new bit of the OpenAPI spec
Description
With an openapi yaml schema that has this content:
requestBody:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/REDACTED'
application/x-www-form-urlencoded:
schema:
type: array
items:
$ref: '#/components/schemas/REDACTED'
multipart/form-data:
schema:
type: array
items:
$ref: '#/components/schemas/REDACTED'
required: true
The generated client has this method:
def _get_kwargs(
*,
client: AuthenticatedClient,
multipart_data: List[REDACTED],
json_body: List[REDACTED],
) -> Dict[str, Any]:
url = "{}/api/redacted/".format(client.base_url)
headers: Dict[str, Any] = client.get_headers()
cookies: Dict[str, Any] = client.get_cookies()
json_json_body = []
for json_body_item_data in json_body:
json_body_item = json_body_item_data.to_dict()
json_json_body.append(json_body_item)
multipart_multipart_data = []
for multipart_data_item_data in multipart_data:
multipart_data_item = multipart_data_item_data.to_dict()
multipart_multipart_data.append(multipart_data_item)
return {
"url": url,
"headers": headers,
"cookies": cookies,
"timeout": client.get_timeout(),
"files": multipart_multipart_data,
}
The diff from the client generated by version 0.9.2 is that it now takes a multipart_data parameter which is now used to populate the files field on the returned dict.
However the json field was removed and the json_body parameter is thus unused. This breaks clients that are passing the json_body field.
Adding it back fixes it, i.e.
return {
"url": url,
"headers": headers,
"cookies": cookies,
"timeout": client.get_timeout(),
"json": json_json_body, # <--- HERE
"files": multipart_multipart_data,
}
Reacted by John Hagen, Ryan Geary, chloecrusan, Mark and Jordan Edmunds
Metadata
Metadata
Assignees
Labels
✨ enhancementNew feature or improvementNew feature or improvement🍭 OpenAPI ComplianceSupporting a new bit of the OpenAPI specSupporting a new bit of the OpenAPI spec
Activity
dbanty commentedon Jul 12, 2021
Interesting, I don’t think we’ve ever added (at least intentionally) support for multiple content types in one endpoint. How do you think this would be most ergonomic in the generated client? Only one content type can actually be sent so the function definition should indicate that somehow.
Should there be a separate function per content type? Or maybe function overloading?
[-]json field is omitted from returned dict in _get_kwargs[/-][+]Support multiple content types for a single endpoint[/+]dpursehouse commentedon Jul 12, 2021
Maybe make both parameters optional, and then raise an exception if both are set, or if neither is set?
dpursehouse commentedon Aug 18, 2021
@dbanty it turns out that this could be solved by explicitly setting
parser_classes = [JSONParser]in the Django view, which prevents the schema generated bydrf-spectacularfrom including the multiple content types.dbanty commentedon Aug 23, 2021
Glad you found a solution @dpursehouse! Would still love to add support for this some day, I'm sure there are others who would benefit from it.
johnthagen commentedon Nov 9, 2021
@dpursehouse
Do you know if this breaks the DRF Web browsable API? (e.g https://www.django-rest-framework.org/ | Web Browsable API: https://restframework.herokuapp.com/) I assumed that the
form_dataportion was used by the browsable API, and disablingform_datacould have unexpected consequences?johnthagen commentedon Nov 9, 2021
@dbanty It seems like this portion might be a bug in its own right.
When I wanted to send
json_bodyinformation in a Patched request (all fields are optional and default toUNSETin the generated client code), this didn't work:I opened up Wireshark on localhost interface to confirm and all of the
PATCHrequests that are sent are blank (no data).I had to move it to the
form_dataparameter to get the data to be sent, but this seems a bit misleading/counter intuitive:dbanty commentedon Nov 9, 2021
I assume this is a limitation in
httpxbut it'd take some testing to be sure. Sending both a form and JSON is quite unusual. I'm guessing it just picks one to send.johnthagen commentedon Nov 9, 2021
johnthagen commentedon Nov 10, 2021
drf-spectacular0.21.0 has a new feature to support excluding certain parsers (content types) to help work around this issue:davidlizeng commentedon Oct 22, 2022
We have an API endpoint where we support uploading a file either as
multipart/form-dataor by specifying anapplication/jsonbody that includes urls to the files. Sample spec:Would love to have a feature where the codegen client would be able to support functions for both the
multipart/form-datarequest as well as theapplication/jsonrequest. The current behavior will handle themultipart/form-datacorrectly, but theapplication/jsonrequests will not work as the json body is dropped during_get_kwargs.In my case, having entirely separate functions for each request would be preferred, as it feels like the interface is strongly typed and most clear. It would mean we'd need to generate names that may look a little long:
upload_file_by_multipart_form_data.pyupload_file_by_application_json.pyThe general pattern would be to roughly look like:
f"{operation_id}_by_{request_content_type}".This would also mean that we no longer have a 1:1 relationship between the api files and the actual paths in the OpenAPI spec. I'm not sure if there is anything that relies on such an assumption?
Would be happy to contribute this feature, but did want to see if it the approach of separate functions makes sense, and is something that the community would be interested in having?
edmundsj commentedon Nov 23, 2022
EDIT: While the below suggestion provides a potential fix, I see this as more of an issue with
drf-spectaculargenerating invalid schemas than an issue withopenapi-generator. If we wantopenapi-generatorto compensate for somewhat-nonsensical schemas, then this fix makes sense to me.I have also run facefirst into this issue multiple times. I have a schema that is being generated by
drf-spectacularfor the purposes of uploading images, and it has multiple content types in the request body:Unfortunately, openapi-generator only uses the first of these definitions, so I am stuck with this auto-generated client function:
Doh! It's trying to convert an image into JSON - clearly not what I am looking for. I have had to avoid using my auto-generated client any time I perform image uploads for this reason and manually submit data via
formData. It's the only place I am not using the generated client and is a glaring violation of DRY.However, most of the content request bodies in my schema have multiple entries in the "content" section, and I only want to specify that formData be uploaded for the image not the myriad of other models I have for which JSON works just fine.
The most elegant way I can think to do this without breaking basic functionality is this algorithm: