web-dev-qa-db-fra.com

Comment obtenir Powershell Invoke-Restmethod pour renvoyer le corps de la réponse du code http 500

L'appel Invoke-RestMethod ne renvoie qu'une exception très inutile ci-dessous et ne vous permet pas (pour autant que je sache) de collecter le contenu du corps (objet JSON affiché dans les résultats de la trace du violon). Cela semble être une mauvaise implémentation si c'est le cas, car la définition de http 500 est assez spécifique pour que le client retourne le corps de la réponse pour aider au dépannage ... Suis-je en train de manquer quelque chose?

invoke-restmethod -method Post -uri "https://api-stage.enviance.com/ver2/EqlService.svc/eql" -Body (ConvertTo-Json $eqlhash)  -Headers @{"Authorization"="Enviance $session"}

invoke-restmethod: Le serveur distant a renvoyé une erreur: (500) Erreur de serveur interne. En ligne: 1 caractère: 9 ...

Trace de violoneux ci-dessous

HTTP/1.1 500 Erreur de serveur interne Connexion: fermer Date: jeu, 12 sept 2013 17:35:00 GMT Serveur: Microsoft-IIS/6.0 X-Powered-By: ASP.NET X-AspNet-Version: 2.0.50727 EnvApi- Version: 2.0,2.0 EnvApi-Remaining-Calls: 994 994 EnvApi-Remaining-Interval: 2684,2684 Cache-Control: no-cache Pragma: no-cache Expires: -1 Content-Type: text/csv; charset = utf-8

{"errorNumber": 0, "message": "L'utilisateur actuel n'a pas le droit de récupérer les données de la table 'CustomFieldTemplate'"}

31
JorgeSandoval

Bien qu'il s'agisse d'un ancien thread, voici une réponse au problème avec les applets de commande Invoke-WebRequest et Invoke-RestMethod.

Celui-ci me dérange depuis un certain temps. Comme toutes les réponses 4xx et 5xx génèrent une exception, vous devez intercepter celle-ci, puis vous pouvez en extraire la réponse. Utilisez-le comme ceci:

$resp = try { Invoke-WebRequest ... } catch { $_.Exception.Response }

Maintenant, $ resp contient toujours tout ce que vous aimez.

24
Anonymous

L'autre réponse vous donne la réponse, mais vous avez besoin d'une étape supplémentaire pour obtenir le corps réel de la réponse, pas seulement les en-têtes. Voici un extrait:

try {
        $result = Invoke-WebRequest ...
}
catch {
        $result = $_.Exception.Response.GetResponseStream()
        $reader = New-Object System.IO.StreamReader($result)
        $reader.BaseStream.Position = 0
        $reader.DiscardBufferedData()
        $responseBody = $reader.ReadToEnd();
}
79
Noah Stahl

Cette solution ne fonctionne plus avec PowerShell 6 - elle ne prend pas en charge GetResponseStream(). Utilisez plutôt

try {
    $result = Invoke-WebRequest ...
}
catch {
    $_.ErrorDetails.Message
}

J'ai écrit une courte fonction d'aide pour prendre en charge PowerShell 6 et versions antérieures:

function ParseErrorForResponseBody($Error) {
    if ($PSVersionTable.PSVersion.Major -lt 6) {
        if ($Error.Exception.Response) {  
            $Reader = New-Object System.IO.StreamReader($Error.Exception.Response.GetResponseStream())
            $Reader.BaseStream.Position = 0
            $Reader.DiscardBufferedData()
            $ResponseBody = $Reader.ReadToEnd()
            if ($ResponseBody.StartsWith('{')) {
                $ResponseBody = $ResponseBody | ConvertFrom-Json
            }
            return $ResponseBody
        }
    }
    else {
        return $Error.ErrorDetails.Message
    }
}

try {
    $result = Invoke-WebRequest ...
}
catch {
    ParseErrorForResponseBody($_)
}
12
Florian Feldhaus

En recherchant une réponse à mon problème, j'ai trouvé ce fil.

Ces solutions ont fonctionné pour moi, mais j'ai dû ajouter deux nouvelles lignes:

 $reader.BaseStream.Position = 0
 $reader.DiscardBufferedData()

Merci!

12
Cisco Cabe

Veuillez noter en tant qu'extension du fournisseur de réponses par Florial Feldhaus le $_.ErrorDetails.Message n'est pas le corps de réponse d'origine. Une expression régulière de suppression de balises HTML est utilisée pour rendre la réponse plus facile à lire lien github . Étant donné que le flux est disposé sur la ligne 1535, il n'existe actuellement aucun moyen de récupérer le corps de réponse d'origine.

La solution consiste à utiliser le dotnet HttpClient pour obtenir la réponse d'origine au lieu d'utiliser le Invoke-WebRequest applet de commande

$url = "http://localhost"
$client = [System.Net.Http.HttpClient]::new()
$request = [System.Net.Http.HttpRequestMessage]::new()
$request.Content = [System.Net.Http.StringContent]::new("Hello World", [System.Text.Encoding]::UTF8, "plain/text")

$result = $client.SendAsync($request).GetAwaiter().GetResult()
$content = $result.Content.ReadAsStringAsync().GetAwaiter().GetResult()

Write-Verbose $content -Verbose

Le problème avec le noyau de Github PowerShell est ici

0
Thomas