5 min czytaniaInżynieria

Jak skrócić URL w PowerShell za pomocą Invoke-RestMethod

Skróć URL w PowerShell za pomocą jednego polecenia cmdlet, obsłuż odpowiedzi 429, przechowuj klucz API poza skryptem i skróć całą kolumnę CSV za pomocą ForEach-Object -Parallel.

Marius Voß
DevRel · edge infra
Jak skrócić URL w PowerShell: Invoke-RestMethod wysyła docelowy URL do API skracacza i zwraca krótki link jako obiekt

Skrócenie URL-a w PowerShell wymaga jednego polecenia cmdlet. Invoke-RestMethod wysyła adres docelowy do API skracacza, przekazuje klucz API w nagłówku Bearer i zwraca przeanalizowany obiekt zamiast ciągu JSON. Nie trzeba nic instalować na żadnym komputerze, na którym jest już PowerShell.

To część serii dla administratorów systemów, która obejmuje także Python, JavaScript, C# i Go. Kształt endpointu i model uwierzytelniania opisano w przeglądzie bezpłatnego API skracacza URL-i, a ścieżkę panelu sterowania w ogólnym przewodniku po skracaniu URL-i.

Najszybszy sposób: jedno wywołanie Invoke-RestMethod

$headers = @{
    Authorization  = "Bearer $env:ELIDO_API_KEY"
    'Content-Type' = 'application/json'
}

$body = @{
    destination_url = 'https://example.com/spring-sale?utm_source=newsletter'
} | ConvertTo-Json

$link = Invoke-RestMethod -Method Post `
    -Uri 'https://api.elido.app/v1/links' `
    -Headers $headers `
    -Body $body `
    -TimeoutSec 10

$link.short_url   # https://s.elido.me/ab12cd

Invoke-RestMethod deserializuje odpowiedź, co odróżnia je od Invoke-WebRequest. Nie ma kroku ConvertFrom-Json ani elementu .Content do rozpakowania: $link jest już obiektem zawierającym id i short_url.

ConvertTo-Json nie jest opcjonalne. Przekazanie tablicy mieszającej bezpośrednio do -Body sprawia, że PowerShell koduje ją jako formularz, API widzi application/x-www-form-urlencoded, a Ty otrzymujesz odpowiedź 400, która wygląda jak problem po stronie serwera.

Jedna niespodzianka specyficzna dla PowerShell: odpowiedź 401 lub 404 jest tutaj błędem kończącym działanie, a nie wartością zwracaną. Każdy inny klient z tej serii każe sprawdzić kod statusu, a ten wymaga przechwycenia wyjątku.

Obsługa odpowiedzi 429 i możliwość ponownego uruchomienia skryptu

W przypadku każdego zadania wykonywanego według harmonogramu trzeba dodać trzy rzeczy. Try/catch z powodu opisanego wyżej sposobu zgłaszania błędów. Oczekiwanie uwzględniające Retry-After. Oraz Idempotency-Key, aby ponowiona próba zwróciła oryginalny link zamiast tworzyć drugi dla tego samego adresu docelowego.

function Get-ShortLink {
    param(
        [Parameter(Mandatory)][string] $Destination,
        [int] $Attempts = 3
    )

    # stable key: the same destination always produces the same one
    $sha  = [System.Security.Cryptography.SHA256]::Create()
    $key  = [BitConverter]::ToString(
                $sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($Destination))
            ).Replace('-', '')

    $headers = @{
        Authorization     = "Bearer $env:ELIDO_API_KEY"
        'Content-Type'    = 'application/json'
        'Idempotency-Key' = $key
    }
    $body = @{ destination_url = $Destination } | ConvertTo-Json

    for ($attempt = 0; $attempt -lt $Attempts; $attempt++) {
        try {
            return (Invoke-RestMethod -Method Post -Uri 'https://api.elido.app/v1/links' `
                        -Headers $headers -Body $body -TimeoutSec 10).short_url
        }
        catch {
            $status = $_.Exception.Response.StatusCode.value__

            if ($status -eq 429) {
                $wait = $_.Exception.Response.Headers['Retry-After']
                if (-not $wait) { $wait = 2 }        # works on 5.1 too; no ?? operator
                Start-Sleep -Seconds ([int]$wait)
            }
            elseif ($status -ge 500) {
                Start-Sleep -Seconds ([math]::Pow(2, $attempt))   # 1s, 2s, 4s
            }
            else {
                throw   # 401, 403, 422: retrying will not help
            }
        }
    }

    throw "shorten failed after $Attempts attempts"
}

W PowerShell 7 możesz pominąć większość analizy wyjątków za pomocą -SkipHttpErrorCheck, które zwraca obiekt odpowiedzi zamiast zgłaszać błąd, dzięki czemu możesz bezpośrednio odczytać treść błędu API. Warto to zrobić podczas diagnozowania odpowiedzi 422, gdy chcesz sprawdzić, które pole zostało odrzucone przez API.

PowerShell Invoke-RestMethod wysyła docelowy URL z tokenem Bearer i Idempotency-Key do endpointu linków skracacza i zwraca przeanalizowany obiekt zawierający short_url

Przechowuj klucz poza skryptem

$env:ELIDO_API_KEY to najprostsza odpowiedź i wystarcza w przypadku zadania według harmonogramu z własnym kontem usługi. Klucz wpisany do pliku .ps1 nie jest dobrym rozwiązaniem: trafia do repozytorium kodu, do Get-History i do każdego logowania transkrypcji włączonego w środowisku.

W przypadku czegokolwiek współdzielonego lepszym miejscem jest moduł SecretManagement:

$env:ELIDO_API_KEY = Get-Secret -Name ElidoApiKey -AsPlainText

Rotacja klucza oznacza wtedy aktualizację jednego wpisu w magazynie zamiast przeszukiwania skryptów na czterech serwerach.

Chcesz uruchomić te przykłady bez zmian? Utwórz klucz w bezpłatnym planie, ustaw $env:ELIDO_API_KEY, a wszystko na tej stronie zadziała bez modyfikacji.

Skracanie całej kolumny CSV

Typowe zadanie w praktyce to nie jeden URL, lecz arkusz z wieloma adresami. Cztery polecenia cmdlet i ograniczenie współbieżności:

$rows    = Import-Csv .\campaign-urls.csv     # columns: id, destination
$funcDef = ${function:Get-ShortLink}.ToString()

$done = $rows | ForEach-Object -ThrottleLimit 8 -Parallel {
    $function:Get-ShortLink = $using:funcDef   # ship the function into each runspace
    [pscustomobject]@{
        id          = $_.id
        destination = $_.destination
        short_url   = try   { Get-ShortLink -Destination $_.destination }
                      catch { "ERROR: $($_.Exception.Message)" }
    }
}

$done | Export-Csv .\campaign-urls-short.csv -NoTypeInformation

-ThrottleLimit 8 to cały sekret: niezależnie od tego, czy plik ma pięćdziesiąt wierszy, czy pięćdziesiąt tysięcy, jednocześnie wykonywanych jest osiem żądań. Z opcją -Parallel wiążą się dwa haczyki. Każda iteracja działa we własnym runspace, więc funkcje i zmienne wywołującego nie są widoczne, chyba że przekażesz je za pomocą $using:. Opcja wymaga też PowerShell 7; w Windows PowerShell 5.1 zwykła pętla foreach jest uczciwą odpowiedzią dla kilkuset wierszy.

Zapisywanie błędów w kolumnie wynikowej zamiast ich zgłaszania pozwala bez problemu ponowić wykonanie. Ponieważ klucz idempotencji pochodzi z adresu docelowego, po poprawieniu trzech wierszy możesz ponownie uruchomić cały plik bez kosztów i bez tworzenia duplikatów.

Czteroetapowy potok PowerShell importuje plik CSV z adresami docelowymi, wywołuje API skracacza dla każdego wiersza z ograniczeniem współbieżności, eksportuje krótkie linki i wyrywkowo sprawdza wynik

Przed wydrukowaniem lub wysłaniem czegokolwiek e-mailem sprawdź losowo kilka wyników. curl.exe -sI https://s.elido.me/ab12cd dla trzech wierszy zajmuje dziesięć sekund i wykrywa przypadek, w którym kolumna została przesunięta o jeden.

Kiedy PowerShell jest właściwym narzędziem

To właściwe narzędzie, gdy dane są już w pliku CSV lub w Active Directory, zadanie działa w harmonogramie systemu Windows albo utrzymuje je administrator systemów, a nie programista aplikacji. W przypadku czegokolwiek, co trafia do aplikacji, wersja C# z typowanym klientem i wstrzykiwaniem zależności jest łatwiejsza do testowania.

W obu przypadkach użyj klucza ze środowiska lub magazynu, jawnego -TimeoutSec, try/catch wokół wywołania oraz stabilnego klucza idempotencji dla wszystkiego, co może uruchomić się dwukrotnie. Strona API i SDK opisuje wygenerowanych klientów, a rozwiązania dla programistów pokazują, co jeszcze udostępnia API.

Zapoznaj się z serią artykułów filarowych

Ten artykuł należy do klastra engineering. Zacznij od przewodnika po bezpłatnym API skracacza URL-i, a następnie przeczytaj o limitach zapytań API skracacza URL-i i idempotencji. Aktualna dokumentacja znajduje się w dokumentacji API, a artykuł masowe importowanie krótkich linków z Arkusza Google opisuje ścieżkę bez kodu dla tego samego zadania z plikiem CSV.

Powiązane artykuły na blogu

Najczęściej zadawane pytania

Jak skrócić URL w PowerShell?

Wywołaj Invoke-RestMethod z opcją -Method Post dla endpointu linków skracacza, przekazując klucz API w nagłówku Authorization, a adres docelowy jako JSON. Polecenie cmdlet analizuje odpowiedź, więc $link.short_url jest od razu dostępne bez kroku ConvertFrom-Json.

Czy potrzebuję modułu, aby skracać URL-e w PowerShell?

Nie. Invoke-RestMethod jest wbudowane w Windows PowerShell 3.0 i każdą wersję PowerShell 7, a wywołanie skracacza to pojedyncze żądanie. Moduły mają sens, gdy potrzebujesz opakowanych w polecenia cmdlet wywołań wielu endpointów, a nie jednego żądania POST.

Dlaczego Invoke-RestMethod zgłasza błąd dla odpowiedzi 404 lub 401?

Ponieważ traktuje każdą odpowiedź 4xx lub 5xx jako błąd kończący działanie, odwrotnie niż większość klientów HTTP. Umieść wywołanie w try/catch albo przekaż -SkipHttpErrorCheck w PowerShell 7, aby otrzymać z powrotem obiekt odpowiedzi i odczytać treść błędu zwróconą przez API.

Jak przechowywać klucz API poza skryptem PowerShell?

Odczytaj go ze zmiennej środowiskowej za pomocą $env:ELIDO_API_KEY albo przechowuj go w module SecretManagement i pobieraj za pomocą Get-Secret. Klucz wklejony do pliku .ps1 trafia do repozytorium kodu, historii konsoli oraz każdego włączonego logowania transkrypcji.

Jak skrócić całą kolumnę URL-i z pliku CSV?

Zaimportuj plik za pomocą Import-Csv, przekaż go przez ForEach-Object -Parallel z opcją -ThrottleLimit 8 i wyeksportuj wynik za pomocą Export-Csv, umieszczając krótki link obok oryginału. Ograniczenie współbieżności utrzymuje wykonanie poniżej limitu zapytań API; bez niego duży plik uruchamia wszystkie żądania jednocześnie.

Czy ForEach-Object -Parallel działa w Windows PowerShell 5.1?

Nie, wymaga PowerShell 7 lub nowszego. W wersji 5.1 praktycznymi opcjami są zwykła pętla foreach, która sprawdza się dla kilkuset wierszy, albo pule runspace, jeśli partia jest na tyle duża, że uzasadnia dodatkowy kod.

Wypróbuj Elido

Wklej URL, otrzymaj krótki link

Bez rejestracji. Link działa 30 dni. Zarejestruj się, aby zachować go na zawsze.

Za darmo, bez rejestracji · 2 dziennie

Wypróbuj Elido

Skracarka URL hostowana w UE: własne domeny, głęboka analityka i otwarte API. Darmowy plan - bez karty kredytowej.

Tagi
how to shorten a url in powershell
powershell url shortener
invoke-restmethod post json
url shortener api powershell
powershell bulk shorten urls
powershell csv api script

Czytaj dalej