6 min de leituraEngenharia

Como encurtar uma URL no PowerShell com Invoke-RestMethod

Encurte uma URL no PowerShell com um cmdlet, trate respostas 429, mantenha a chave de API fora do script e encurte uma coluna inteira de CSV com ForEach-Object -Parallel.

Marius Voß
DevRel · edge infra
Como encurtar uma URL no PowerShell: Invoke-RestMethod enviando uma URL de destino para a API do encurtador e retornando o link curto como um objeto

Encurtar uma URL no PowerShell exige um único cmdlet. Invoke-RestMethod envia seu destino para a API do encurtador, manda a chave de API como um cabeçalho Bearer e devolve um objeto analisado, em vez de uma string de JSON. Não há nada para instalar em qualquer máquina que já tenha PowerShell.

Este é o capítulo de administração de sistemas de uma série que também aborda Python, JavaScript, C# e Go. O formato do endpoint e o modelo de autenticação estão documentados na visão geral da API gratuita de encurtador de URLs; a rota do painel está no guia geral sobre como encurtar uma URL.

A Maneira Mais Rápida: Uma Chamada a 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 desserializa a resposta, e essa é a diferença entre ele e Invoke-WebRequest. Não há uma etapa ConvertFrom-Json nem um .Content para desembrulhar: $link já é um objeto com id e short_url.

ConvertTo-Json não é opcional. Se você passar uma tabela hash diretamente para -Body, o PowerShell a codifica como formulário, a API recebe application/x-www-form-urlencoded e você obtém um 400 que parece um problema do servidor.

Uma surpresa específica do PowerShell: um 401 ou 404 é um erro terminante aqui, não um valor de retorno. Todos os outros clientes desta série fazem você verificar um código de status; este faz você capturar uma exceção.

Trate os 429 e Mantenha o Script Reexecutável

Para qualquer tarefa agendada, é preciso adicionar três coisas. Um try/catch, por causa do comportamento de geração de erros mencionado acima. Uma espera que respeite Retry-After. E uma Idempotency-Key, para que uma requisição repetida retorne o link original em vez de criar um segundo para o mesmo destino.

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

No PowerShell 7, você pode evitar a maior parte da investigação de exceções com -SkipHttpErrorCheck, que retorna o objeto de resposta em vez de gerar um erro, para que você possa ler diretamente o corpo de erro da API. Vale a pena fazer isso ao depurar um 422 e querer ver qual campo gerou a objeção da API.

Invoke-RestMethod do PowerShell enviando uma URL de destino com um token Bearer e uma Idempotency-Key para o endpoint de links do encurtador e retornando um objeto analisado que contém short_url

Mantenha a Chave Fora do Script

$env:ELIDO_API_KEY é a resposta mais simples e é suficiente para uma tarefa agendada com sua própria conta de serviço. Uma chave digitada no arquivo .ps1, não: ela vai parar no controle de versão, em Get-History e em qualquer registro de transcrição que esteja ativado no ambiente.

Para qualquer coisa compartilhada, o módulo SecretManagement é um lugar melhor:

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

Rotacionar uma chave passa a significar atualizar uma única entrada do cofre, em vez de procurá-la em scripts de quatro servidores.

Quer executar tudo como está escrito? Crie uma chave no plano gratuito, defina $env:ELIDO_API_KEY e tudo nesta página funcionará sem alterações.

Encurte uma Coluna Inteira de CSV

A tarefa real mais comum não é uma URL, mas uma planilha cheia delas. Quatro cmdlets e um limite:

$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 é todo o segredo: oito requisições em andamento, independentemente de o arquivo ter cinquenta linhas ou cinquenta mil. -Parallel traz duas armadilhas. Cada iteração é executada em seu próprio runspace, então as funções e variáveis do chamador não ficam visíveis a menos que você as passe com $using:. E ele requer o PowerShell 7; no Windows PowerShell 5.1, um foreach comum é a resposta honesta para algumas centenas de linhas.

Escrever os erros na coluna de saída em vez de gerar um erro mantém a execução reexecutável. Como a chave de idempotência é derivada do destino, executar o arquivo inteiro novamente depois de corrigir três linhas não custa nada nem cria duplicatas.

Um pipeline de PowerShell em quatro etapas que importa um CSV de destinos, chama a API do encurtador por linha com um limite de requisições, exporta os links curtos e verifica alguns resultados

Faça uma verificação pontual antes de qualquer coisa ser impressa ou enviada por e-mail. curl.exe -sI https://s.elido.me/ab12cd em três linhas leva dez segundos e detecta o caso em que uma coluna ficou deslocada uma posição.

Quando o PowerShell é a Ferramenta Certa

Ele é a ferramenta certa quando os dados já estão em um CSV ou no Active Directory, quando o trabalho é executado em uma tarefa agendada do Windows ou quando a pessoa que o mantém é um administrador de sistemas, e não um desenvolvedor de aplicações. Para qualquer coisa que seja distribuída dentro de uma aplicação, a versão em C# com um cliente tipado e injeção de dependência é mais fácil de testar.

De qualquer forma: chave vinda do ambiente ou de um cofre, um -TimeoutSec explícito, try/catch ao redor da chamada e uma chave de idempotência estável em qualquer coisa que possa ser executada duas vezes. A página de API e SDKs aborda os clientes gerados, e soluções para desenvolvedores mostra o que mais a API oferece.

Leia a Série Principal

Este artigo está no cluster de engenharia. Comece pelo guia da API gratuita de encurtador de URLs e depois leia limites de requisições e idempotência. A referência atualizada está na documentação da API, e importe links curtos em massa de uma Planilha Google aborda o caminho sem código para o mesmo trabalho com CSV.

Relacionado no Blog

Perguntas frequentes

Como encurto uma URL no PowerShell?

Chame Invoke-RestMethod com -Method Post no endpoint de links do encurtador, passando sua chave de API em um cabeçalho Authorization e o destino como JSON. O cmdlet analisa a resposta para você, então $link.short_url fica disponível imediatamente, sem uma etapa ConvertFrom-Json.

Preciso de um módulo para encurtar URLs no PowerShell?

Não. Invoke-RestMethod vem integrado ao Windows PowerShell 3.0 e a todas as versões do PowerShell 7, e uma chamada ao encurtador é uma única requisição. Módulos valem a pena quando você quer wrappers no formato de cmdlets para muitos endpoints, em vez de um único POST.

Por que Invoke-RestMethod gera um erro em um 404 ou 401?

Porque ele trata qualquer 4xx ou 5xx como um erro terminante, o oposto do comportamento da maioria dos clientes HTTP. Envolva a chamada em try/catch ou passe -SkipHttpErrorCheck no PowerShell 7 para receber o objeto de resposta e ler o corpo do erro retornado pela API.

Como mantenho a chave de API fora de um script do PowerShell?

Leia-a de uma variável de ambiente com $env:ELIDO_API_KEY ou armazene-a com o módulo SecretManagement e busque-a com Get-Secret. Uma chave colada em um arquivo .ps1 acaba no controle de versão, no histórico do console e em qualquer registro de transcrição que esteja ativado.

Como encurto uma coluna inteira de URLs de um CSV?

Use Import-Csv no arquivo, envie-o por ForEach-Object -Parallel com -ThrottleLimit 8 e use Export-Csv no resultado, com o link curto ao lado do original. O limite é o que mantém a execução dentro do limite de requisições da API; sem ele, um arquivo grande inicia todas as requisições ao mesmo tempo.

ForEach-Object -Parallel funciona no Windows PowerShell 5.1?

Não, ele requer o PowerShell 7 ou posterior. No 5.1, as opções práticas são um loop foreach comum, que funciona bem para algumas centenas de linhas, ou pools de runspaces, se o lote for grande o bastante para justificar o código adicional.

Experimente Elido

Cole uma URL, obtenha um link curto

Sem cadastro. O link vive 30 dias. Cadastre-se para mantê-lo para sempre.

Grátis, sem necessidade de registo · 2 por dia

Experimente o Elido

Encurtador de URL hospedado na UE: domínios personalizados, análises profundas e API aberta. Plano gratuito - sem cartão de crédito.

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

Continuar lendo