Gdy praca z REST bokiem wychodzi…
Praca w środowisku hybrydowym, z mieszanką serwerów korzystających z Windows z (przeważającą) flotą Linuksów wymaga wspólnego języka. W naszej firmie korzystamy z REST i nie tylko oferujemy końcówki dla innych działów, ale sami też staramy się korzystać z tych końcówek w naszych funkcjach. Wszystko to działa na komercyjnej wersji PowerShell Universal (PSU). I działa całkiem sprawnie – jedna rzecz tylko nie dawała nam spokoju, przesyłaniem parametrów do naszych końcówek w sposób “PowerShellowy”.
Z początku uznaliśmy, że to usterka w PSU. Szybko jednak okazało się, że problem leży po stronie samego PowerShella a konkretniej, tego jak działa Invoke-RestMethod.
Może najpierw kilka słów o samym problemie. Mamy dwa polecenia: jedno powinno utworzyć alias w DNS, drugie ten sam alias powinno usunąć. Pierwsza działa bezbłędnie, drugie zdaje się ignorować przekazywane parametry i zwraca błąd:
Invoke-RestMethod -Uri http://psu.contoso.com/dns/cname -Method Post -Body @{ | |
nazwa = 'test' | |
cel = 'host.contoso.com.' | |
} -UseDefaultCredentials | |
Invoke-RestMethod -Uri http://psu.contoso.com/dns/cname -Method Delete -Body @{ | |
nazwa = 'test' | |
cel = 'host.contoso.com.' | |
} -UseDefaultCredentials | |
# Invoke-RestMethod: Cannot process command because of one or more missing mandatory parameters: Nazwa Cel. | |
# at , : line 1 |
Po kilku testach okazało się, że jedynie Post reaguje poprawnie na parametry przesyłane za pomocą tablicy skrótów przekazywanej do parametru Body. Szybko okazało się jednak, że to Invoke-RestMethod zmienia swe zachowanie w zależności od wykonywanej metody. Sprawdzić można to dość łatwo korzystając ze strony Webhook.site – dla metody POST typ zawartości jest określony, a parametry poprawnie interpretowane:
Dla metody DELETE – typ zawartości nie jest zdefiniowany, zawartość nie jest więc poprawnie interpretowana:
Koniec końców okazało się, że zamiast polegać na PowerShellu, który za nas doda informację o zawartości, możemy po prostu typ zawartości określić sami:
Invoke-RestMethod -Uri http://psu.contoso.com/dns/cname -Method Delete -Body @{ | |
nazwa = 'test' | |
cel = 'host.contoso.com.' | |
} -UseDefaultCredentials -ContentType application/x-www-form-urlencoded |
Jedyny problem, to że trzeba o przekazywaniu typu zawartości pamiętać za każdym razem. Z drugiej strony alternatywa (przekazywanie parametrów w ramach URL) była jednak bardziej kłopotliwa.