2016-03-29 1 views
8

Ich schrieb ein kleines PowerShell-Skript, um eine Anfrage an einen Server zu senden und ein einfaches XML-Ergebnis zurück zu bekommen.Warum sind Invoke-WebRequest und Invoke-RestMethod gleichzeitig fehlgeschlagen und erfolgreich?

Powershell-Skript

$xml = "<?xml version='1.0' encoding='utf-8'?><Search><ID>278A87E1-1BC2-4E19-82E9-8BBE31D67D20</ID></Search>" 
$response = Invoke-RestMethod -Method Post -Uri "http://localhost/search" -ContentType "application/xml" -Body $xml 

Das ist es, wirklich einfach und es gibt keinen Grund, dass ich sehen kann, denn es scheitern. Ich habe auch versucht, das Skript mit Invoke-WebRequest und beide fehlschlagen. Der zurückgegebene Fehler ist Invoke-RestMethod : Value cannot be null. Parameter name: name. Die seltsame Sache ist, dass, wenn ich dies mit Wireshark überwachen, sehe ich die Verbindung, sehe ich die POST und ich sehe das Ergebnis vom Server und alles sieht perfekt gut, aber das Cmdlet sagt, es ist fehlgeschlagen (und ja, der Returncode ist 200).

Wenn ich den Invoke-WebRequest/Invoke-RestMethod mit dem -OutFile Parameter ausführen, läuft es gut ohne Fehler und speichert das Ergebnis in der angegebenen Datei; -OutVariable schlägt fehl, falls Sie sich fragen.

Das Ergebnis ist eine XML-Datei, die Header geben an, dass es xml ist und das XML ordnungsgemäß formatiert ist.

Ergebnis, wenn erfolgreich

<?xml version="1.0" encoding="UTF-8" ?> 
<Result version="1.0" xmlns="urn:xmlns-org"> 
    <searchID>{278a87e1-1bc2-4e19-82e9-8bbe31d67d20}</searchID> 
    <responseStatus>true</responseStatus> 
    <responseStatusStrg>MORE</responseStatusStrg> 
    <numOfMatches>40</numOfMatches> 
</Result> 

Weiß jemand, warum die Invoke-XXX Cmdlets ein Fehler zurückgegeben und was ich kann es zu beheben tun? Auch hier funktioniert es einwandfrei, wenn ich den Parameter -OutFile verwende. Selbst wenn es fehlschlägt, kann ich eine korrekte Konversation zwischen dem Skript und dem Server in Wireshark sehen.

Auch, wenn ich -Verbose verwenden es sagt mir folgendes:

VERBOSE: POST http://localhost/search with -1-byte payload 
VERBOSE: received X-byte response of content type application/xml; charset="UTF-8" 

Wo X-byte die tatsächliche Größe der Antwort ist, aber es unterscheidet sich offensichtlich mit jeder Antwort auf die an den Server gesendeten Daten abhängig. Ich finde es nur seltsam, dass das Cmdlet fehlschlägt, aber sagt, dass es eine Antwort mit Daten empfangen hat und dass es eine -1-byte Nutzlast gesendet hat.

Antwort

7

Ich ging voran und schaute in den Invoke-WebRequest Cmdlet-Code und fand heraus, warum es mit diesem bestimmten Fehler fehlschlägt.

Es schlägt bei einem Anruf zu System.Globalization.EncodingTable.GetCodePageFromName fehl. Die Codierung wird an diese Funktion als Parameter übergeben und die Codierung wird vom Cmdlet über den Header Content-Type abgerufen. Bei diesem Server wurde der Content-Type in der Antwort als Content-Type: application/xml; charset="UTF-8" zurückgesendet.

Das Problem dabei ist, dass Angebote für das Einwickeln des Wertes in charset nicht Standard sind, so dass die Cmdlets parsen es aus wie "UTF-8" anstelle der gültigen UTF-8. Das Cmdlet übergibt "UTF-8" an die Funktion, und die Funktion löst eine Ausnahme aus, die besagt, dass die angegebene Codierung ungültig ist. Das ist in Ordnung und würde viel mehr Sinn machen, wenn das in der letzten Ausnahme berichtet wird, aber das ist es nicht.

Die ungültige Codierung Ausnahme wird durch die Microsoft.PowerShell.Commands.ContentHelper.GetEncodingOrDefault Funktion und in der Ausnahmebehandler es GetEncoding ruft wieder gefangen, aber mit einem Null-Parameter, der für den Parameter name im endgültigen ArgumentNullException führt.

Microsoft.PowerShell.Commands.ContentHelper.GetEncodingOrDefault

internal static Encoding GetEncodingOrDefault(string characterSet) 
{ 
    string name = string.IsNullOrEmpty(characterSet) ? "ISO-8859-1" : characterSet; 
    try 
    { 
    return Encoding.GetEncoding(name); 
    } 
    catch (ArgumentException ex) 
    { 
    return Encoding.GetEncoding((string) null); 
    } 
} 

Der Aufruf von GetEncoding innerhalb der catch-Anweisung löst den folgenden Code innerhalb GetCodePageFromName die sich von GetEncoding

if (name==null) { 
    throw new ArgumentNullException("name"); 
} 

Power aufgerufen geht das richtig um, da es technisch ein ungültiger Wert ist, aber Sie würden denken, sie würdenanrufennur um sicher zu sein.

+0

Ich stoße auf dieses Problem mit Python 2.7 'SimpleHTTPServer'. – Kupiakos

+0

Vielen Dank für die Entdeckung der Ursache. Ich habe dieses Manifest in einer vollständig gepatchten Windows Server 2012 R2-Box mit installierter PowerShell (WMF) 5.1 gesehen. Nehmen Sie den gleichen Code auf Windows 10 oder Windows Server 2016 und es gibt kein Problem. Sehr enttäuschend, da scheint es keine Lösung zu geben. – Lewis

Verwandte Themen