5 min de leituraEngenharia

CLI de encurtador de URL: encurte links pelo terminal

Encurte uma URL pela linha de comando com curl e jq, envolva o comando em uma função de shell, copie para a área de transferência e encurte um arquivo inteiro com xargs em paralelo.

Marius Voß
DevRel · edge infra
CLI de encurtador de URL: um POST com curl encadeado ao jq para imprimir um link curto direto no terminal e na área de transferência

Encurtar uma URL pelo terminal é uma linha:

curl -s -X POST https://api.elido.app/v1/links \
  -H "Authorization: Bearer $ELIDO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"destination_url":"https://example.com/spring-sale"}' | jq -r .short_url

Isso imprime https://s.elido.me/ab12cd e nada mais. O curl faz a solicitação, o jq extrai um campo do JSON, e -r remove as aspas ao redor para que o valor possa ir direto para a área de transferência ou para outro comando.

O restante deste post apresenta as quatro melhorias que transformam essa linha em algo que você realmente usa: uma função de shell, códigos de saída confiáveis, processamento em lote com concorrência limitada e a área de transferência. Se você preferir escrever em uma linguagem em vez de usar o shell, a mesma chamada existe em Python, Go e seis outros runtimes.

Um pipeline de terminal enviando uma URL de destino com curl, recebendo a resposta JSON e encadeando-a ao jq para imprimir o link curto e copiá-lo para a área de transferência

Transforme em um comando

Um alias não aceita um argumento, então use uma função. Em .zshrc ou .bashrc:

short() {
  [ -z "$1" ] && { echo "usage: short <url> [slug]" >&2; return 2; }

  local body
  body=$(jq -n --arg url "$1" --arg slug "${2:-}" \
    '{destination_url: $url} + (if $slug == "" then {} else {slug: $slug} end)')

  curl -s --fail-with-body -X POST https://api.elido.app/v1/links \
    -H "Authorization: Bearer $ELIDO_API_KEY" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: $(printf %s "$1" | shasum -a 256 | cut -d' ' -f1)" \
    -d "$body" | jq -r .short_url
}

Há três escolhas deliberadas aí.

Construir o JSON com jq -n --arg, em vez de interpolar strings, significa que um destino contendo aspas ou um e comercial não quebra a solicitação. Esse é o equivalente no shell ao SQL parametrizado, e ignorá-lo é a mesma classe de bug.

--fail-with-body é a flag que as pessoas esquecem. Por padrão, o curl sai com código 0 para qualquer troca concluída, então um 401 passa pelo pipe, o jq imprime null e um script continua com null onde deveria estar um link. Com ela, um 4xx define um status de saída diferente de zero e você ainda recebe o corpo do erro para ler.

A Idempotency-Key derivada da URL significa que executar o mesmo comando duas vezes retorna o mesmo link em vez de criar dois. Isso importa mais na seção de processamento em lote abaixo, e o raciocínio está em limites de taxa e idempotência.

Precisa de uma chave? Crie uma no plano gratuito, exporte-a pelo seu perfil de shell e a função funcionará no próximo terminal novo.

Direto para a área de transferência

Os últimos caracteres que fazem tudo parecer pronto:

short "https://example.com/spring-sale" | tee /dev/tty | pbcopy      # macOS
short "https://example.com/spring-sale" | tee /dev/tty | xclip -sel c # Linux, X11
short "https://example.com/spring-sale" | tee /dev/tty | wl-copy     # Wayland
short "https://example.com/spring-sale" | tee /dev/tty | clip.exe    # WSL

tee /dev/tty imprime o link e o copia ao mesmo tempo, o que é melhor do que copiar às cegas e torcer.

Processamento em lote sem acumular 429

Quatro melhorias de um curl de uma linha para uma ferramenta de linha de comando utilizável: uma função de shell, falhar de forma explícita, processamento em lote com xargs em paralelo e integração com a área de transferência

Um arquivo de URLs, uma por linha, encurtadas oito por vez:

export -f short                      # bash; zsh users call the script directly
xargs -P 8 -I{} bash -c 'short "{}"' < urls.txt > short-urls.txt

-P 8 é toda a estratégia de limite de taxa: oito solicitações em andamento, independentemente de o arquivo ter cinquenta linhas ou cinquenta mil. Sem isso, o xargs as executa tão rápido quanto consegue criar processos, e a API responde 429 à maioria.

Há duas ressalvas que vale conhecer antes de apontar isso para um arquivo real. xargs -P intercala a saída, então as linhas podem chegar fora de ordem. Se o mapeamento entre entrada e saída for importante, imprima ambos:

xargs -P 8 -I{} bash -c 'printf "%s\t%s\n" "{}" "$(short "{}")"' < urls.txt > mapping.tsv

E uma URL contendo um espaço ou uma aspa não sobreviverá ao -I{} sem escape. Para qualquer entrada fornecida por usuário, xargs -0 com um arquivo de entrada delimitado por nulo é a versão segura. Nesse ponto, um script real em Python costuma dar menos trabalho do que acertar as aspas.

Mantenha a chave fora do seu histórico

ELIDO_API_KEY=abc123 short <url> coloca a chave em ~/.zsh_history e na lista de processos, onde qualquer outra conta na máquina pode lê-la com ps.

Em vez disso, exporte-a pelo seu perfil de shell ou, melhor ainda, busque-a de um armazenamento de segredos no início do shell:

export ELIDO_API_KEY="$(security find-generic-password -s elido -w)"      # macOS Keychain
export ELIDO_API_KEY="$(pass show elido/api-key)"                          # pass

Rotacionar uma chave passa a significar atualizar uma entrada, em vez de procurar em arquivos ocultos espalhados por três máquinas. O mesmo princípio se aplica ao lado do servidor de qualquer script que você agende, e webhooks para eventos de link é o padrão para receber dados de volta sem outra chave vivendo em algum lugar.

Quando o terminal é o lugar certo

Ele é o lugar certo quando as URLs já estão em um arquivo, quando você já está em um shell ou quando o encurtamento é uma etapa de um script maior: um processo de release que gera um link de distribuição, um trabalho de CI que encurta a URL de uma implantação de prévia, um hook do git que produz um link para uma entrada do changelog.

É o lugar errado para gerenciar uma campanha. Pastas, tags e a comparação do volume de cliques entre posicionamentos precisam de um painel, e tentar fazer isso com consultas do jq contra um endpoint de listagem vira um projeto, não um atalho. Soluções para desenvolvedores explica o que a API oferece além da criação, e a API e os SDKs explica os clientes tipados para quando um script de shell deixar de ser suficiente.

Leia a série principal

Este artigo faz parte do cluster de engenharia. Comece com o guia gratuito da API de encurtador de URL para entender o formato do endpoint e depois leia limites de taxa e idempotência. A referência atual é a documentação da API.

Relacionados no blog

Perguntas frequentes

Como encurto uma URL pela linha de comando?

Envie o destino à API do encurtador com curl e encadeie a resposta ao jq para extrair o link curto. Uma linha, sem instalar nada além de curl e jq, e a chave de API vem de uma variável de ambiente para nunca aparecer no histórico do shell.

Como transformo isso em um comando reutilizável?

Envolva a chamada do curl em uma função de shell no seu .zshrc ou .bashrc, usando a URL como primeiro argumento. Recarregue o perfil e short https://example.com funciona de qualquer diretório. Uma função é melhor que um alias aqui porque precisa aceitar um argumento.

Por que meu pipeline do curl é bem-sucedido quando a API retornou 401?

Porque o curl sai com código 0 para qualquer troca HTTP concluída, inclusive respostas de erro. Adicione --fail-with-body para que um 4xx ou 5xx defina um código de saída diferente de zero e o corpo ainda seja impresso. Caso contrário, um script continua com um objeto de erro onde deveria estar o link curto.

Como encurto um arquivo inteiro de URLs pelo shell?

Encadeie o arquivo ao xargs com -P 8 para executar oito solicitações por vez e use -I{} para substituir cada linha. Isso limita a concorrência a oito, independentemente do tamanho do arquivo, e mantém um lote grande abaixo do limite de taxa da API em vez de acumular respostas 429.

Como copio o link curto diretamente para a área de transferência?

Encadeie a saída ao pbcopy no macOS, a xclip -selection clipboard no Linux com X11, a wl-copy no Wayland ou a clip.exe no WSL. Combinado com uma função de shell, isso significa que um comando produz um link já pronto para colar.

Onde a chave de API deve ficar em um fluxo de trabalho de CLI?

Em uma variável de ambiente exportada pelo seu perfil de shell ou, melhor ainda, obtida de um gerenciador de senhas ou armazenamento de segredos no início do shell. Digitar a chave na linha de comando a coloca no arquivo de histórico e na lista de processos, onde qualquer outro usuário da máquina pode lê-la.

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
url shortener cli
shorten url command line
curl url shortener
shorten url terminal
bash shorten link function
xargs parallel api calls

Continuar lendo