5 Min. LesezeitEngineering

Eine URL in PowerShell mit Invoke-RestMethod kürzen

Kürzen Sie eine URL in PowerShell mit einem Cmdlet, behandeln Sie anschließend 429-Fehler, halten Sie den API-Schlüssel aus dem Skript heraus und kürzen Sie eine ganze CSV-Spalte mit ForEach-Object -Parallel.

Marius Voß
DevRel · edge infra
Eine URL in PowerShell kürzen: Invoke-RestMethod sendet eine Ziel-URL an eine Kürzer-API und gibt den Kurzlink als Objekt zurück

Eine URL in PowerShell zu kürzen erfordert nur ein Cmdlet. Invoke-RestMethod sendet Ihr Ziel an die API des Kürzers, übermittelt den API-Schlüssel als Bearer-Header und gibt ein analysiertes Objekt statt einer JSON-Zeichenkette zurück. Sie müssen nichts installieren, sofern PowerShell auf dem Rechner bereits vorhanden ist.

Dies ist der Sysadmin-Teil einer Serie, die auch Python, JavaScript, C# und Go behandelt. Aufbau und Authentifizierungsmodell des Endpunkts sind in der Übersicht zur kostenlosen URL-Kürzer-API dokumentiert; die Route zum Dashboard finden Sie im allgemeinen Leitfaden zum Kürzen einer URL.

Der schnellste Weg: Ein Aufruf von 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 deserialisiert die Antwort. Das ist der Unterschied zu Invoke-WebRequest. Es gibt keinen ConvertFrom-Json-Schritt und kein .Content, das Sie auspacken müssten: $link ist bereits ein Objekt mit id und short_url.

ConvertTo-Json ist nicht optional. Übergeben Sie eine Hashtabelle direkt an -Body, codiert PowerShell sie als Formulardaten, die API sieht application/x-www-form-urlencoded und Sie erhalten einen 400-Fehler, der wie ein Serverproblem aussieht.

Eine PowerShell-spezifische Überraschung: Ein 401 oder 404 ist hier ein beendender Fehler und kein Rückgabewert. Bei jedem anderen Client dieser Serie müssen Sie einen Statuscode prüfen; hier müssen Sie eine Exception abfangen.

429-Fehler behandeln und das Skript wiederholbar halten

Für alles, was geplant ausgeführt wird, müssen Sie drei Dinge ergänzen. Ein try/catch wegen des oben beschriebenen Auslöseverhaltens. Eine Wartezeit, die Retry-After beachtet. Und einen Idempotency-Key, damit eine wiederholte Anfrage den ursprünglichen Link zurückgibt, statt für dasselbe Ziel einen zweiten zu erstellen.

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"
}

Unter PowerShell 7 können Sie sich mit -SkipHttpErrorCheck den größten Teil der Exception-Analyse sparen. Dadurch wird das Antwortobjekt zurückgegeben, statt eine Exception auszulösen, sodass Sie den Fehler-Body der API direkt lesen können. Das ist beim Debuggen eines 422-Fehlers sinnvoll, wenn Sie sehen möchten, welches Feld die API beanstandet hat.

PowerShell Invoke-RestMethod sendet eine Ziel-URL mit Bearer-Token und Idempotency-Key an den Links-Endpunkt des Kürzers und gibt ein analysiertes Objekt mit short_url zurück

Den Schlüssel aus dem Skript heraushalten

$env:ELIDO_API_KEY ist die unkomplizierte Lösung und für eine geplante Aufgabe mit einem eigenen Dienstkonto ausreichend. Ein in die .ps1-Datei eingetragener Schlüssel ist es nicht: Er landet in der Quellcodeverwaltung, in Get-History und in jeder Transkriptprotokollierung, die in Ihrer Umgebung aktiviert wurde.

Für alles, was gemeinsam genutzt wird, ist das SecretManagement-Modul der bessere Ort:

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

Einen Schlüssel zu rotieren bedeutet dann, einen Eintrag im Tresor zu aktualisieren, statt Skripte auf vier Servern zu durchsuchen.

Möchten Sie diese Befehle unverändert ausführen? Erstellen Sie einen Schlüssel im kostenlosen Tarif, setzen Sie $env:ELIDO_API_KEY, und alles auf dieser Seite funktioniert unverändert.

Eine ganze CSV-Spalte kürzen

Die häufige Aufgabe aus der Praxis ist nicht eine einzelne URL, sondern eine Tabelle voller URLs. Vier Cmdlets und eine Begrenzung:

$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 ist der gesamte Trick: Es laufen immer acht Anfragen gleichzeitig, unabhängig davon, ob die Datei fünfzig oder fünfzigtausend Zeilen enthält. -Parallel bringt zwei Stolpersteine mit sich. Jede Iteration läuft in ihrem eigenen Runspace, daher sind Funktionen und Variablen des aufrufenden Prozesses nicht sichtbar, sofern Sie sie nicht mit $using: übergeben. Außerdem benötigen Sie PowerShell 7; unter Windows PowerShell 5.1 ist eine einfache foreach-Schleife für einige hundert Zeilen die vernünftige Lösung.

Wenn Sie Fehler in die Ausgabespalte schreiben, statt Exceptions auszulösen, bleibt die Ausführung wiederholbar. Da der Idempotency-Key aus dem Ziel abgeleitet wird, kostet es nichts und erzeugt keine Duplikate, die gesamte Datei nach der Korrektur von drei Zeilen erneut auszuführen.

Eine vierstufige PowerShell-Pipeline importiert eine CSV-Datei mit Zielen, ruft für jede Zeile die Kürzer-API mit einer Begrenzung auf, exportiert die Kurzlinks und prüft das Ergebnis stichprobenartig

Prüfen Sie stichprobenartig, bevor irgendetwas ausgegeben oder per E-Mail versendet wird. curl.exe -sI https://s.elido.me/ab12cd für drei Zeilen dauert zehn Sekunden und findet den Fall, in dem eine Spalte um eins verrutscht ist.

Wann PowerShell das richtige Werkzeug ist

PowerShell ist das richtige Werkzeug, wenn die Daten bereits in einer CSV-Datei oder im Active Directory liegen, wenn der Job als geplante Windows-Aufgabe läuft oder wenn die betreuende Person Sysadmin und nicht Anwendungsentwickler ist. Für alles, was innerhalb einer Anwendung ausgeliefert wird, lässt sich die C#-Version mit typisiertem Client und Dependency Injection leichter testen.

So oder so gilt: Schlüssel aus der Umgebung oder einem Tresor, ein explizites -TimeoutSec, try/catch um den Aufruf und ein stabiler Idempotency-Key für alles, was zweimal ausgeführt werden könnte. Die Seite API und SDKs behandelt die generierten Clients, und Lösungen für Entwickler beschreibt, was die API sonst noch anbietet.

Die Cornerstone-Serie lesen

Dieser Beitrag gehört zum Engineering-Cluster. Beginnen Sie mit dem Leitfaden zur kostenlosen URL-Kürzer-API, danach mit Rate-Limits und Idempotenz. Die aktuelle Referenz sind die API-Dokumente, und Kurzlinks aus einem Google Sheet per Massenimport anlegen behandelt den No-Code-Weg für denselben CSV-Job.

Verwandte Beiträge im Blog

Häufig gestellte Fragen

Wie kürze ich eine URL in PowerShell?

Rufen Sie Invoke-RestMethod mit -Method Post für den Links-Endpunkt des Kürzers auf, übergeben Sie Ihren API-Schlüssel in einem Authorization-Header und das Ziel als JSON. Das Cmdlet analysiert die Antwort für Sie, sodass $link.short_url sofort ohne einen ConvertFrom-Json-Schritt verfügbar ist.

Benötige ich ein Modul, um URLs in PowerShell zu kürzen?

Nein. Invoke-RestMethod ist in Windows PowerShell 3.0 und jeder Version von PowerShell 7 enthalten, und ein Aufruf des Kürzers besteht aus einer einzigen Anfrage. Module lohnen sich, wenn Sie Cmdlet-ähnliche Wrapper für viele Endpunkte statt nur für einen POST benötigen.

Warum löst Invoke-RestMethod bei einem 404 oder 401 einen Fehler aus?

Weil es jeden 4xx- oder 5xx-Status als beendenden Fehler behandelt, also genau anders als die meisten HTTP-Clients. Umschließen Sie den Aufruf mit try/catch oder übergeben Sie unter PowerShell 7 -SkipHttpErrorCheck, um das Antwortobjekt zurückzubekommen und den von der API zurückgegebenen Fehler-Body zu lesen.

Wie halte ich den API-Schlüssel aus einem PowerShell-Skript heraus?

Lesen Sie ihn mit $env:ELIDO_API_KEY aus einer Umgebungsvariable oder speichern Sie ihn mit dem SecretManagement-Modul und rufen Sie ihn mit Get-Secret ab. Ein in eine .ps1-Datei eingefügter Schlüssel landet in der Quellcodeverwaltung, im Konsolenverlauf und in jeder aktivierten Transkriptprotokollierung.

Wie kürze ich eine ganze URL-Spalte aus einer CSV-Datei?

Importieren Sie die Datei mit Import-Csv, leiten Sie sie mit ForEach-Object -Parallel und -ThrottleLimit 8 weiter und schreiben Sie das Ergebnis mit Export-Csv, wobei der Kurzlink neben dem Original steht. Die Begrenzung hält die Ausführung unter dem API-Rate-Limit; ohne sie startet eine große Datei alle Anfragen gleichzeitig.

Funktioniert ForEach-Object -Parallel in Windows PowerShell 5.1?

Nein, dafür benötigen Sie PowerShell 7 oder höher. Unter 5.1 sind eine einfache foreach-Schleife, die für einige hundert Zeilen ausreicht, oder Runspace-Pools die praktischen Optionen, wenn der Batch groß genug ist, um den zusätzlichen Code zu rechtfertigen.

Elido testen

URL einfügen, kurzer Link in Sekunden

Kein Konto nötig. Link bleibt 30 Tage aktiv. Konto erstellen, um ihn dauerhaft zu behalten.

Kostenlos, keine Anmeldung erforderlich · 2 pro Tag

Elido testen

URL-Shortener mit EU-Hosting: eigene Domains, tiefe Analytik und eine offene API. Kostenloser Tarif - keine Kreditkarte nötig.

Tags
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

Weiterlesen