Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PowerShell] (multipart/form-data request) and proxy behaviour #18315

Merged
merged 15 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ function Invoke-{{{apiNamePrefix}}}ApiClient {

$Configuration = Get-{{{apiNamePrefix}}}Configuration
$RequestUri = $Configuration["BaseUrl"] + $Uri
$DefaultHeaders = $Configuration["DefaultHeaders"]
# should make sure that SkipCertificateCheck is not set for PowerShell 5
$SkipCertificateCheck = $Configuration["SkipCertificateCheck"]
$Proxy = $Configuration["Proxy"]

# cookie parameters
foreach ($Parameter in $CookieParameters.GetEnumerator()) {
Expand All @@ -56,19 +59,17 @@ function Invoke-{{{apiNamePrefix}}}ApiClient {
$HeaderParameters['Accept'] = $Accept
}

[string]$MultiPartBoundary = $null
$ContentType= SelectHeaders -Headers $ContentTypes
# Content-Type and multipart handling
$ContentType = SelectHeaders -Headers $ContentTypes
if ($ContentType) {
$HeaderParameters['Content-Type'] = $ContentType
if ($ContentType -eq 'multipart/form-data') {
[string]$MultiPartBoundary = [System.Guid]::NewGuid()
$MultiPartBoundary = "---------------------------$MultiPartBoundary"
$HeaderParameters['Content-Type'] = "$ContentType; boundary=$MultiPartBoundary"
$MultiPart = $true
}
}

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

Expand All @@ -89,30 +90,7 @@ function Invoke-{{{apiNamePrefix}}}ApiClient {

# 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
}
$RequestBody = $FormParameters
}

if ($Body -or $IsBodyNullable) {
Expand Down Expand Up @@ -141,54 +119,55 @@ function Invoke-{{{apiNamePrefix}}}ApiClient {
}

{{/hasHttpSignatureMethods}}
# use splatting to pass parameters
$Params = @{}
$Params.Uri = $UriBuilder.Uri
$Params.Method = $Method
$Params.Headers = $HeaderParameters
$Params.ErrorAction = 'Stop'

if ($SkipCertificateCheck -eq $true) {
if ($null -eq $Configuration["Proxy"]) {
# skip certification check, no proxy
$Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
-Method $Method `
-Headers $HeaderParameters `
-Body $RequestBody `
-ErrorAction Stop `
-UseBasicParsing `
-SkipCertificateCheck
} else {
# skip certification check, use proxy
$Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
-Method $Method `
-Headers $HeaderParameters `
-Body $RequestBody `
-ErrorAction Stop `
-UseBasicParsing `
-SkipCertificateCheck `
-Proxy $Configuration["Proxy"].GetProxy($UriBuilder.Uri) `
-ProxyUseDefaultCredentials
$Params.SkipCertificateCheck = $true
}

if ($null -ne $Proxy) {
$effectiveProxy = $Proxy.GetProxy($UriBuilder.Uri)
# do not set proxy if it is null or same as target Uri
if ($null -ne $effectiveProxy -and $effectiveProxy.AbsoluteUri -ne $UriBuilder.Uri) {
$Params.Proxy = $effectiveProxy.AbsoluteUri
$Params.ProxyUseDefaultCredentials = $true
}
} else {
if ($null -eq $Configuration["Proxy"]) {
# perform certification check, no proxy
$Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
-Method $Method `
-Headers $HeaderParameters `
-Body $RequestBody `
-ErrorAction Stop `
-UseBasicParsing
}

# use Invoke-RestApi if Content-Type is 'multipart/form-data', Invoke-WebRequest otherwise
if ($MultiPart) {
if ($PSVersionTable.PSVersion.Major -eq 5) {
# preset null return values as not supported by Invoke-RestMethod on PS5
$ResponseHeaders = $null
$ResponseStatusCode = $null
} else {
# perform certification check, use proxy
$Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
-Method $Method `
-Headers $HeaderParameters `
-Body $RequestBody `
-ErrorAction Stop `
-UseBasicParsing `
-Proxy $Configuration["Proxy"].GetProxy($UriBuilder.Uri) `
-ProxyUseDefaultCredentials
# preset return variables
$Params.ResponseHeadersVariable = "ResponseHeaders"
$Params.StatusCodeVariable = "ResponseStatusCode"
}
}
$Params.Form = $FormParameters
$Response = Invoke-RestMethod @Params

return @{
Response = $Response
StatusCode = $ResponseStatusCode
Headers = $ResponseHeaders
}
} else {
$Params.Body = $RequestBody
$Params.UseBasicParsing = $true
$Response = Invoke-WebRequest @Params

return @{
Response = DeserializeResponse -Response $Response.Content -ReturnType $ReturnType -ContentTypes $Response.Headers["Content-Type"]
StatusCode = $Response.StatusCode
Headers = $Response.Headers
return @{
Response = DeserializeResponse -Response $Response.Content -ReturnType $ReturnType -ContentTypes $Response.Headers["Content-Type"]
StatusCode = $Response.StatusCode
Headers = $Response.Headers
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ function Invoke-ApiClient {

$Configuration = Get-Configuration
$RequestUri = $Configuration["BaseUrl"] + $Uri
$DefaultHeaders = $Configuration["DefaultHeaders"]
# should make sure that SkipCertificateCheck is not set for PowerShell 5
$SkipCertificateCheck = $Configuration["SkipCertificateCheck"]
$Proxy = $Configuration["Proxy"]

# cookie parameters
foreach ($Parameter in $CookieParameters.GetEnumerator()) {
Expand All @@ -63,19 +66,17 @@ function Invoke-ApiClient {
$HeaderParameters['Accept'] = $Accept
}

[string]$MultiPartBoundary = $null
$ContentType= SelectHeaders -Headers $ContentTypes
# Content-Type and multipart handling
$ContentType = SelectHeaders -Headers $ContentTypes
if ($ContentType) {
$HeaderParameters['Content-Type'] = $ContentType
if ($ContentType -eq 'multipart/form-data') {
[string]$MultiPartBoundary = [System.Guid]::NewGuid()
$MultiPartBoundary = "---------------------------$MultiPartBoundary"
$HeaderParameters['Content-Type'] = "$ContentType; boundary=$MultiPartBoundary"
$MultiPart = $true
}
}

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

Expand All @@ -96,30 +97,7 @@ function Invoke-ApiClient {

# 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
}
$RequestBody = $FormParameters
}

if ($Body -or $IsBodyNullable) {
Expand All @@ -129,54 +107,55 @@ function Invoke-ApiClient {
}
}

# use splatting to pass parameters
$Params = @{}
$Params.Uri = $UriBuilder.Uri
$Params.Method = $Method
$Params.Headers = $HeaderParameters
$Params.ErrorAction = 'Stop'

if ($SkipCertificateCheck -eq $true) {
if ($null -eq $Configuration["Proxy"]) {
# skip certification check, no proxy
$Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
-Method $Method `
-Headers $HeaderParameters `
-Body $RequestBody `
-ErrorAction Stop `
-UseBasicParsing `
-SkipCertificateCheck
} else {
# skip certification check, use proxy
$Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
-Method $Method `
-Headers $HeaderParameters `
-Body $RequestBody `
-ErrorAction Stop `
-UseBasicParsing `
-SkipCertificateCheck `
-Proxy $Configuration["Proxy"].GetProxy($UriBuilder.Uri) `
-ProxyUseDefaultCredentials
$Params.SkipCertificateCheck = $true
}

if ($null -ne $Proxy) {
$effectiveProxy = $Proxy.GetProxy($UriBuilder.Uri)
# do not set proxy if it is null or same as target Uri
if ($null -ne $effectiveProxy -and $effectiveProxy.AbsoluteUri -ne $UriBuilder.Uri) {
$Params.Proxy = $effectiveProxy.AbsoluteUri
$Params.ProxyUseDefaultCredentials = $true
}
} else {
if ($null -eq $Configuration["Proxy"]) {
# perform certification check, no proxy
$Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
-Method $Method `
-Headers $HeaderParameters `
-Body $RequestBody `
-ErrorAction Stop `
-UseBasicParsing
}

# use Invoke-RestApi if Content-Type is 'multipart/form-data', Invoke-WebRequest otherwise
if ($MultiPart) {
if ($PSVersionTable.PSVersion.Major -eq 5) {
# preset null return values as not supported by Invoke-RestMethod on PS5
$ResponseHeaders = $null
$ResponseStatusCode = $null
} else {
# perform certification check, use proxy
$Response = Invoke-WebRequest -Uri $UriBuilder.Uri `
-Method $Method `
-Headers $HeaderParameters `
-Body $RequestBody `
-ErrorAction Stop `
-UseBasicParsing `
-Proxy $Configuration["Proxy"].GetProxy($UriBuilder.Uri) `
-ProxyUseDefaultCredentials
# preset return variables
$Params.ResponseHeadersVariable = "ResponseHeaders"
$Params.StatusCodeVariable = "ResponseStatusCode"
}
}
$Params.Form = $FormParameters
$Response = Invoke-RestMethod @Params

return @{
Response = $Response
StatusCode = $ResponseStatusCode
Headers = $ResponseHeaders
}
} else {
$Params.Body = $RequestBody
$Params.UseBasicParsing = $true
$Response = Invoke-WebRequest @Params

return @{
Response = DeserializeResponse -Response $Response.Content -ReturnType $ReturnType -ContentTypes $Response.Headers["Content-Type"]
StatusCode = $Response.StatusCode
Headers = $Response.Headers
return @{
Response = DeserializeResponse -Response $Response.Content -ReturnType $ReturnType -ContentTypes $Response.Headers["Content-Type"]
StatusCode = $Response.StatusCode
Headers = $Response.Headers
}
}
}

Expand Down
Loading
Loading