4 хв читанняІнженерія

CLI сервісу скорочення URL: скорочуйте посилання з термінала

Скорочуйте URL із командного рядка за допомогою curl і jq, обгорніть виклик у функцію оболонки, копіюйте результат у буфер обміну та скорочуйте цілий файл паралельно через xargs.

Marius Voß
DevRel · edge infra
CLI сервісу скорочення URL: POST-запит через curl, переданий у jq, щоб вивести коротке посилання прямо в термінал і скопіювати його в буфер обміну

Скоротити URL із термінала можна одним рядком:

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

Ця команда виводить https://s.elido.me/ab12cd і нічого більше. curl надсилає запит, jq витягує одне поле з JSON, а -r прибирає зовнішні лапки, щоб значення можна було одразу передати в буфер обміну або іншу команду.

Решта цієї статті присвячена чотирьом удосконаленням, які перетворюють цей рядок на інструмент, яким справді користуєшся: функції оболонки, коректним кодам завершення, масовій обробці з обмеженою паралельністю та буферу обміну. Якщо вам зручніше писати мовою програмування, а не мовою оболонки, такий самий виклик є у Python, Go і ще шести середовищах виконання.

Конвеєр у терміналі надсилає URL призначення через curl, отримує відповідь JSON і передає її через jq, щоб вивести коротке посилання та скопіювати його в буфер обміну

Перетворіть це на команду

Псевдонім не може приймати аргумент, тому використайте функцію. У .zshrc або .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
}

У цьому коді є три свідомі рішення.

Побудова JSON за допомогою jq -n --arg, а не інтерполяції рядків, означає, що адреса призначення з лапкою або амперсандом не зламає запит. Це оболонковий еквівалент параметризованого SQL, і пропуск цього кроку створює той самий клас помилок.

--fail-with-body - прапорець, про який часто забувають. За замовчуванням curl завершується з кодом 0 після будь-якого завершеного обміну, тому відповідь 401 проходить конвеєр, jq виводить null, а скрипт продовжує роботу з null там, де мало бути посилання. З цим прапорцем відповідь 4xx встановлює ненульовий статус завершення, і ви все одно отримуєте тіло помилки для перегляду.

Idempotency-Key, отриманий з URL, означає, що повторний запуск тієї самої команди повертає те саме посилання, а не створює два. Це ще важливіше в розділі про масову обробку нижче, а пояснення наведено в матеріалі про ліміти запитів та ідемпотентність.

Потрібен ключ? Створіть його на безкоштовному плані, експортуйте з профілю оболонки, і функція працюватиме в наступному новому терміналі.

Одразу в буфер обміну

Останні кілька символів, завдяки яким усе здається завершеним:

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 одночасно виводить посилання й копіює його, тож це зручніше, ніж копіювати навмання й сподіватися на результат.

Масова обробка без накопичення 429

Чотири вдосконалення від однорядкового curl до зручного інструмента командного рядка: функція оболонки, гучне завершення з помилкою, масова обробка через xargs паралельно та інтеграція з буфером обміну

Файл із URL, які скорочуються по вісім за раз:

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

-P 8 - уся стратегія роботи з лімітом: одночасно виконується вісім запитів незалежно від того, містить файл п'ятдесят рядків чи п'ятдесят тисяч. Без цього xargs запускає процеси з максимально можливою швидкістю, і API відповідає 429 на більшість запитів.

Перед передаванням справжнього файлу варто знати про два нюанси. xargs -P перемішує вивід, тому рядки можуть прийти не в тому порядку; якщо відповідність між входом і виходом важлива, виводьте обидва значення:

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

А URL, що містить пробіл або лапку, не переживе -I{} без екранування. Для будь-яких даних, наданих користувачем, безпечним варіантом буде xargs -0 із файлом, де записи розділені нульовим байтом. На цьому етапі написати справжній скрипт на Python зазвичай простіше, ніж правильно налаштувати лапки.

Не залишайте ключ в історії

ELIDO_API_KEY=abc123 short <url> записує ключ у ~/.zsh_history і список процесів, де його зможе прочитати будь-який інший обліковий запис на комп'ютері за допомогою ps.

Експортуйте ключ із профілю оболонки або, ще краще, отримуйте його зі сховища секретів під час запуску оболонки:

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

Тоді для ротації ключа достатньо оновити один запис, а не шукати його в прихованих файлах на трьох комп'ютерах. Той самий принцип діє на серверній стороні будь-якого запланованого скрипту, а вебхуки для подій посилань показують підхід до отримання даних без зберігання ще одного ключа десь у системі.

Коли термінал є правильним місцем

Термінал підходить, коли URL уже є у файлі, ви вже працюєте в оболонці або скорочення є одним із кроків більшого скрипту: процес випуску, який генерує посилання на дистрибутив, завдання CI, що скорочує URL розгортання попереднього перегляду, або git-хук, який створює посилання для запису в журналі змін.

Термінал не підходить для керування кампанією. Для папок, тегів і порівняння кількості кліків у різних місцях розміщення потрібен дашборд, а спроба робити це за допомогою запитів jq до кінцевої точки списку перетворюється на окремий проєкт, а не на швидке рішення. У розділі рішення для розробників описано можливості API за межами створення, а в матеріалі про API та SDK розглянуто типізовані клієнти на випадок, коли скрипту оболонки вже недостатньо.

Читайте основну серію

Ця стаття входить до інженерного кластера. Почніть із посібника з безкоштовного API сервісу скорочення URL, щоб ознайомитися зі структурою кінцевої точки, а потім прочитайте про ліміти запитів та ідемпотентність. Актуальна довідка доступна в документації API.

Пов'язані статті в блозі

Поширені запитання

Як скоротити URL із командного рядка?

Надішліть адресу призначення до API сервісу скорочення через curl і передайте відповідь у jq, щоб витягнути коротке посилання. Один рядок, нічого не потрібно встановлювати, крім curl і jq, а ключ API надходить зі змінної середовища, тому ніколи не з'являється в історії оболонки.

Як перетворити це на команду для повторного використання?

Огорніть виклик curl у функцію оболонки у вашому .zshrc або .bashrc, передаючи URL як перший аргумент. Перезавантажте профіль, і short https://example.com працюватиме з будь-якого каталогу. Тут функція краща за псевдонім, тому що їй потрібно приймати аргумент.

Чому мій конвеєр curl завершується успішно, якщо API повернув 401?

Тому що curl завершується з кодом 0 після будь-якого завершеного обміну HTTP, зокрема після відповіді з помилкою. Додайте --fail-with-body, щоб для відповіді 4xx або 5xx встановлювався ненульовий код завершення, а тіло все одно виводилося. Інакше скрипт продовжить роботу з об'єктом помилки там, де мало бути коротке посилання.

Як скоротити цілий файл URL з оболонки?

Передайте файл у xargs із параметром -P 8, щоб одночасно виконувати вісім запитів, і -I{}, щоб підставляти кожен рядок. Це обмежує паралельність вісьмома запитами незалежно від довжини файлу, завдяки чому великий пакет не перевищує ліміт API і не накопичує відповіді 429.

Як скопіювати коротке посилання безпосередньо в буфер обміну?

Передайте результат у pbcopy на macOS, xclip -selection clipboard у Linux з X11, wl-copy у Wayland або clip.exe у WSL. Разом із функцією оболонки це означає, що одна команда створює посилання, уже готове до вставлення.

Де зберігати ключ API для роботи з CLI?

У змінній середовища, експортованій із профілю оболонки, або, ще краще, отримувати його під час запуску оболонки з менеджера паролів чи сховища секретів. Якщо ввести ключ безпосередньо в команду, він потрапить у файл історії та список процесів, де його зможе прочитати будь-який інший користувач комп'ютера.

Спробуйте Elido

Вставте URL - отримайте коротке посилання

Без реєстрації. Посилання живе 30 днів. Зареєструйтесь, щоб зберегти назавжди.

Безкоштовно, без реєстрації · 2 на день

Спробуйте Elido

URL-скорочувач із хостингом у ЄС: власні домени, глибока аналітика, відкритий API. Безкоштовний тариф - без кредитної картки.

Теги
url shortener cli
shorten url command line
curl url shortener
shorten url terminal
bash shorten link function
xargs parallel api calls

Читати далі