1
votes

I'm trying to use the Azure Cognitive Services API with Powershell to 'read' the contents of a .jpg in a blob store. Everything I am trying to do works perfectly using the Azure API demo/test page, so I am fairly sure that this, to a degree, proves that some elements I'm using in my code are valid. Well, at least they are when using the API testing tool.

Here is my Powershell:

Clear-Host

$myUri      = "<ENDPOINT value from "keys and endpoint blade">/vision/v3.0/read/analyze?language=en"
$imagePath  = "<path to image in blob. accessible online and anonymously>"
$subKey     = "<KEY #1 from "keys and endpoint" blade>"

$headersHash = @{}
$headersHash.Add( "Host", "westeurope.api.cognitive.microsoft.com" )
$headersHash.Add( "Ocp-Apim-Subscription-Key", $subKey )
$headersHash.Add( "Content-Type","application/json" )

$bodyHash = @{ "url" = $imagePath }

out-host -InputObject "Sending request:"
$response = Invoke-WebRequest -uri $myUri `
    -Method Post `
    -Headers $headersHash `
    -Body $bodyHash `
    -verbose

"Response: $response"

When I send that, all I ever get is a:

Invoke-WebRequest : The remote server returned an error: (400) Bad Request.
At C:\scratch\testy.ps1:15 char:13
+ $response = Invoke-WebRequest -uri $myUri `
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-W 
    ebRequest], WebException
    + FullyQualifiedErrorId : 
    WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

I must be missing something basic but I cannot see what. There are no published examples of using Powershell to access the CS APIs that I can find but there is an example with Python (requests) and I'm pretty sure I'm emulating and representing what goes into the Python example correctly. But then again, its not working so something isn't right.

Strangely, when I try to recreate this in Postman, I get a 202 but no response body, so its not possible for me to view or extract the apim-request-id in order to manufacture the next request to retrieve the results.

1
Please do not post answers as part of the question. And definitely don't post non-answers as answers. I've corrected the problem here. Please follow this model in the future. Stack Overflow is not a discussion forum. If you haven't already, please take the tour. - Cody Gray
Apologies, Cody. Have looked at the tour and get it now. Thanks for fixing. - Indrid

1 Answers

0
votes

Found the issue. The problem was made clear when I wrapped the call in a try/catch block and put this in the catch block:

$streamReader = 
[System.IO.StreamReader]::new($_.Exception.Response.GetResponseStream())
    $ErrResp = $streamReader.ReadToEnd() | ConvertFrom-Json
$streamReader.Close()

I was then able to look at the contents of the $ErrResp variable and there was a fragment of a string which said "unable to download target image.." or something to that effect. Odd because I could use the URL I was supplying to instantly connect to and get the image.. so it had to be the way the URL was being injecting into the body.

It was.

When using a hashtable as the body, where your Content-Type is 'application/json' all you need to do, it seems, is use convertto-json with your hash first. This worked and I instantly got my 202 and the pointer to where to collect my results.

Hopefully this will help someone, somewhere, sometime.