OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.8k stars 6.58k forks source link

[BUG][Powershell] Multipart form data is not properly supported #8347

Closed EngineerCoding closed 3 years ago

EngineerCoding commented 3 years ago

Bug Report Checklist

Description

Multipart form data is not properly supported as the boundary is not set properly. Content type is only set correctly (although missing the boundary)

openapi-generator version

latest

Generation Details
Steps to reproduce

A powershell client with against a spec with multipart/form data. Note that the backend is ASP.Net core with an endpoint taking just IFormFile (without [FromForm]) and spec is generated with NSwag.

Invoke method with a correct FileInfo, and the client will raise an error (cannot decode the response: this error indicates that the boundary is missing)

Suggestion for a fix

Temporarily I have added support in my local ApiClient.ps1 (Invoke-ApiClient). This definitely could use a clean up but works for at least uploading a single file. This has not been tested with regular values, but should work.

    [string]$MultiPartBoundary = $null
    $ContentType= SelectHeaders -Headers $ContentTypes
    if ($ContentType) {
        $HeaderParameters['Content-Type'] = $ContentType # Use this line to see where I bodged this code
        if ($ContentType -eq 'multipart/form-data') {
            [string]$MultiPartBoundary = [System.Guid]::NewGuid()
            $MultiPartBoundary = "---------------------------$MultiPartBoundary"

            $HeaderParameters['Content-Type'] = "$ContentType; boundary=$MultiPartBoundary"
        }
    }

    # add default headers if any
    foreach ($header in $Configuration["DefaultHeaders"].GetEnumerator()) {
        $HeaderParameters[$header.Name] = $header.Value
    }

    # construct URL query string
    $HttpValues = [System.Web.HttpUtility]::ParseQueryString([String]::Empty)
    foreach ($Parameter in $QueryParameters.GetEnumerator()) {
        if ($Parameter.Value.Count -gt 1) { // array
            foreach ($Value in $Parameter.Value) {
                $HttpValues.Add($Parameter.Key + '[]', $Value)
            }
        } else {
            $HttpValues.Add($Parameter.Key,$Parameter.Value)
        }
    }
    # Build the request and load it with the query string.
    $UriBuilder = [System.UriBuilder]($RequestUri)
    $UriBuilder.Query = $HttpValues.ToString()

    # include form parameters in the request body
    if ($FormParameters -and $FormParameters.Count -gt 0) {
        if (![string]::IsNullOrEmpty($MultiPartBoundary)) {
            $RequestBody = ""
            $LF = "`r`n"
            $FormParameters.Keys | ForEach-Object {
                $value = $FormParameters[$_]
                $isFile = $value.GetType().FullName -eq "System.IO.FileInfo"

                $RequestBody += "--$MultiPartBoundary$LF"
                $RequestBody += "Content-Disposition: form-data; name=`"$_`""
                if ($isFile) {
                    $fileName = $value.Name
                    $RequestBody += "; filename=`"$fileName`"$LF"
                    $RequestBody += "Content-Type: application/octet-stream$LF$LF"
                    $RequestBody += Get-Content -Path $value.FullName
                } else {
                    $RequestBody += "$LF$LF"
                    $RequestBody += ([string]$value)
                }
                $RequestBody += "$LF--$MultiPartBoundary"
            }
            $RequestBody += "--"
        } else {
            $RequestBody = $FormParameters
        }
    }
wing328 commented 3 years ago

@EngineerCoding You're right. It's not yet supported.

We would appreciate a PR for such enhancement. Thank you.