Kontrynuując poprzedni wpis, który wprowadzał podstawy curl
czas na bardziej zaawansowane techniki i triki, które warto dodać do naszych umiejętności.
Czy jesteś programistą, testerem czy po prostu użytkownikiem curl’a, który ułatwia sobie pracę z API – ten wpis może Ci się przydać!
Przy okazji muszę Wam wspomnieć: Julia Evans tworzy cudowne, rysowane cheatsheets dla różnych narzędzi sieciowych, komend terminala (linux/unix), jakiś czas temu zrobiła taką ściągę dla curl
:
curl pic.twitter.com/1PZ28kJr09
— 🔎Julia Evans🔍 (@b0rk) January 26, 2019
Jeśli jeszcze jej nie znacie koniecznie zajrzyjcie na wizardzines.com
Spis trików:
- Odpowiedź z nagłówkami serwera
- Dokumentacja curl zawsze pod ręką
- Wysyłanie formularzy z poziomu terminala
- Przesyłanie plików przez curl
- Pobieranie pliku przez curl
- Wznowienie pobierania pliku
- Pobieranie wielu plików na raz
- Pobieranie wielu plików na podstawie listy linków
- Wyświetlenie paska postępu pobierania
- Generowanie i automatyzacja adresów URL
- Bonus trik – skopiuj curl prosto z przeglądarki
1. Odpowiedź z nagłówkami serwera
Jeżeli wyślemy zapytanie GET do API za pomocą curl
w podstawowy sposób otrzymamy coś takiego:
curl example.com
i w odpowiedzi kod HTML tej strony
<!doctype html> <html> <head> <title>Example Domain</title> <meta charset="utf-8" /> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style type="text/css"> body { ...
Jednak możemy skorzystać z opcji -i
albo --include
, aby otrzymać również nagłówki odpowiedzi serwera
curl -i example.com
wynik:
HTTP/1.1 200 OK Age: 557583 Cache-Control: max-age=604800 Content-Type: text/html; charset=UTF-8 Date: Thu, 16 Feb 2023 15:18:07 GMT Etag: "3147526947+ident" Expires: Thu, 23 Feb 2023 15:18:07 GMT Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT Server: ECS (nyb/1D18) Vary: Accept-Encoding X-Cache: HIT Content-Length: 1256 <!doctype html> <html>
Może też być tak, że interesują nas tylko nagłówki, a treść odpowiedzi chcemy pominąć, wówczas powinniśmy użyć opcji -I
(--head
) czyli tryb „info only”.
curl -I example.com
2. Dokumentacja curl zawsze pod ręką
Dokumentacja online curl’a nie jest moją ulubioną. Uczciwie powiem, że źle mi się ją przegląda, na szczęście wersja konsolowa jest znacznie przyjemniejsza i na wyciągnięcie jednej opcji
curl -h
– aby otrzymać skrócone podpowiedzi najpopularniejszych opcji curlcurl -h all
– aby sprawdzić wszystkie opcje z krótkimi opisami
~$ curl -h Usage: curl [options...] <url> -d, --data <data> HTTP POST data -f, --fail Fail silently (no output at all) on HTTP errors -h, --help <category> Get help for commands -i, --include Include protocol response headers in the output -o, --output <file> Write to file instead of stdout -O, --remote-name Write output to a file named as the remote file -s, --silent Silent mode -T, --upload-file <file> Transfer local FILE to destination -u, --user <user:password> Server user and password -A, --user-agent <name> Send User-Agent <name> to server -v, --verbose Make the operation more talkative -V, --version Show version number and quit This is not the full help, this menu is stripped into categories. Use "--help category" to get an overview of all categories. For all options use the manual or "--help all".
3. Wysyłanie formularzy z poziomu terminala curlem
Jeśli wylistujecie wszystkie opcje na pewno zauważycie opcję -F, --form
– to opcja, która pozwala wypełnić formularz by przesłać wiadomość.
Załóżmy, że mamy taki prosty formularz rejestracji:
<form action="/register" method="POST"> <input type="text" name="username"> <input type="email" name="email"> <input type="submit" value="Submit"> </form>
Zapewne aby go przetestować wykonamy następujące zapytanie, które ma zasymulować zachowanie przycisku wyślij (submit):
curl -X POST example.com/register \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=testUser&[email protected]"
Nie musimy dodawać -H "Content-Type: application/x-www-form-urlencoded"
, bo to nagłówek domyślny.
Podany typ application/x-www-form-urlencoded
oznacza, że treść żądania HTTP wysłana do serwera będzie jednym długim query stringiem czyli parami klucz=wartość odzielonymi ampersandem (&).
Co zresztą widzimy w zapytaniu jako: "username=testUser&[email protected]"
Ok, ale co jeśli mam naprawdę długi query string, albo chcę wysłać plik w załączniku za pomocą curl?
Wówczas wracamy do opcji -F
.
→ wysłanie formularza metodą POST za pomocą flagi -d
curl
curl -X POST example.com/register \ -d "username=testUser&[email protected]"
→ wysłanie formularza metodą POST za pomocą flagi -F
curl,
wówczas metoda -X POST
jest opcjonalna:
curl example.com/register \ -F "username=testUser" \ -F "[email protected]"
Zgodnie z dokumentacją form typ application/x-www-form-urlencoded
nie jest odpowiedni kiedy chcemy przesłać dane binarne (nie alfanumeryczne np. plik) lub po prostu duży payload. Wówczas należy skorzystać z typu multipart/form-data
Tu przykład przesłania formularza od razu z wgraniem obrazka:
curl example.com/register \ -F "username=testUser" \ -F "[email protected]" \ -F "[email protected]"
a to prowadzi nas do kolejnego punktu …
4. Przesyłanie plików przez curl
Możemy wgrać / przesłać plik lokalny przez komendę curl
. Możemy dodać plik, który znajduje się u nas w tej samej lokalizacji co wykonujemy komendę curl, nazwa pliku musi być poprzedzona znakiem @
.
Posłużę się podobnym przykładem:
curl example.com/upload \ -F "[email protected]"
ale można też wprost dodać wszystkie opcje (metodę POST i content type):
curl -X POST example.com/upload \ -H "Content-Type: multipart/form-data" \ -F "[email protected]"
5. Pobieranie pliku przez curl
Możemy pobrać plik z tą samą nazwą, co oryginalny plik znajdujący się na serwerze.
Parametr -O / --remote-name
wskazuje (binarny) plik źródłowy, więc jeśli go nie przekażesz, curl nie będzie mógł go pobrać i zwróci błąd (a w najlepszym wypadku uda mu się wykonać podstawowego GETa).
curl -O example.com/file.pdf
Na przykład pobierzmy ściągę z narzędziami konsolowymi:
curl -O https://wizardzines.com/networking-tools-poster.pdf
vs gdy zapomnisz -O
:
curl https://wizardzines.com/networking-tools-poster.pdf
Przykład, który pobierze wam plik o nazwie 000-adr-template.md:
~$ curl -O https://gist.githubusercontent.com/ritaly/1d15b6c96c6bae86597684864ba85e6e/raw/96bfc801ec386de1ae9b331f9e87d97f0e452384/000-adr-template.md % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 379 100 379 0 0 3131 0 --:--:-- --:--:-- --:--:-- 3828
% — pokazuje stan pobierania w procentach;
Total — pokazuje stan pobierania w bajtach (dodatkowe M będzie oznaczało w megabajtach);
Pobieranie pliku przez curl z nadaniem nowej nazwy
Drobny myk z opcją -o
czyli pobranie pliku pod inną nazwę niż ta, pod którą plik jest na serwerze:
curl example.com/file.pdf -o new_file.pdf
6. Wznowienie pobierania pliku
Jeżeli z jakiegoś powodu zaczęliśmy pobierać plik i nastąpiła przerwa, możemy kontynuuować
curl -C - -O example.com/file.pdf
7. Pobieranie wielu plików na raz
curl -O example.com/file1.pdf \ -O example.com/file2.pdf \ -O example.com/fileX.txt
8. Pobieranie wielu plików na podstawie listy linków
Przy wielu plikach, które chcemy pobrać, możemy stworzyć przykładowy plik z linkami i pobrać wszystko jedną komendą.
Załóżmy, że mamy plik myurls.txt
, który zawiera link każdy od nowej linii
example.com/file1.pdf example.com/file2.pdf example.com/fileX.txt
Możemy w terminalu wykonać następującą operację:
xargs -n 1 curl -O < myurls.txt
9. Wyświetlenie paska postępu pobierania
Masz setkę plików do pobrania i chcesz wiedzieć jaki % udało się pobrać? Albo twój plik jest naprawdę duży?
Nie ma sprawy! Opcja -#
dodaje pasek postępu
curl -# -O example.com/hugefile.pdf
np.
curl -# -O https://jvns.ca/wizard-zine.pdf
A w gratisie macie super zin od Julii Evans do poczytania 😉
URL globbing czyli generowanie i automatyzacja odpytywania adresów URL curl’em
Curl posiada pewną opcję, która może być zastosowana do najprostrzych sanity testów i innych ciekawych automatyzacji, a o której sama dowiedziałam się dość późno czyli właśnie URL globbing.
Potrzebujemy zakresu adresów URL, które są w większości takie same – tylko niewielka ich część zmienia się między żądaniami. Przykładem może być np. sprawdzenie czy wszystkie url danego zakresu (zakres liczbowy, zestaw nazw) na stronie odpowiadają 200, wiemy, że adresy są stałe i mają format example.com/[rok]/[miesiac]/posts
Aby przekazać zakres liczbowy musimy użyć nawiasów kwadratowychPrzetestujcie ten przykład:
curl https://jsonplaceholder.typicode.com/posts/[1-5]
(w zależności od używanej konsoli może dodatkowo wymagać eskapowania nawiasów []
, na macu nie mam tego problemu, ale na windowsie konsola może się upomnieć o backslash lub należy użyć cudzysłów)
curl https://jsonplaceholder.typicode.com/posts/\[1-5\] curl "https://jsonplaceholder.typicode.com/posts/[1-5]"
curl
automatycznie odpyta endpointy dla postów od 1 do 5.
Zamiast odpytywać co 1 id, nic nie stoi na przeszkodzie, by dodać parametr „co krok” po dwukropku :
. Np. chcemy sprawdzić co trzeci post:
curl "https://jsonplaceholder.typicode.com/posts/[1-20:3]"
Możemy przekazać konkretny zakres np. id = 3, 10, 25, 8, do tego użyjemy nawiasów klamrowych do przekazania listy parametrów.
Terminal zaznaczy wam klamry jako znak specjalny, więc należy je wyeskapować lub użyć cudzysłów
curl https://jsonplaceholder.typicode.com/posts/\{3,10,25,8\} curl "https://jsonplaceholder.typicode.com/posts/{3,10,25,8}"
Wynik tego zapytania możemy zapisać do pliku zapomocą opcji -o
, co więcej możemy zautomatyzować to zapisywanie tak by każdy wynik otrzymał własny plik wynikowy wystarczy, że stworzymy wzorzec wykorzystując znak #1
, to miejsce zostanie zastąpione kolejnymi wartościami z naszego zakresu
curl https://jsonplaceholder.typicode.com/posts/\{3,10,25,8\} -o output#1.txt curl "https://jsonplaceholder.typicode.com/posts/{3,10,25,8}" -o output#1.txt
Jeśli dodatkowo połączymy to z paskiem progresu -#
, to widzimy jak kolejne zapytania się ładują:
curl https://jsonplaceholder.typicode.com/posts/\{3,10,25,8\}/ -o output#1.txt -#
Możemy też w ten sposób pobierać pliki
curl -O "http://example.com/img/[001-100].png"
czy łączyć zakresy liczbowe, z zakresem alfabetycznym czy listą parametrów:
curl -O "http://example.com/{alfa,beta,gamma,delta}/[100-600:50]x[100-600:50].jpg"
Wracając do pierwszego przykładu: example.com/[rok]/[miesiac]/posts
jeśli rok byłby w formacie YYYY w zakresie od 2013-2023 i miesiące w formacie MM, wystarczy:
curl -O "http://example.com/[2013-2023]/[01-12]"
BONUS: Jak skopiować zapytanie HTTP z przeglądarki jako curl
?
Zupełnie o tym zapomniałam, ale wstawiając na początku posta tweeta Julii uznałam, że to na pewno warty polecenia trick.
Możemy skopiować jako komendę curl
, dowolne żądanie HTTP, które wykonuje się w naszej przeglądarce – Chrome / Firefox czy Safarii, choć przypuszczam, że też inne przeglądarki też umożliwają taką opcję.
- Otwórz DevTools zakładkę Network („Sieć” jeśli używasz wersji polskiej) .
- Prawym przyciskiem myszy (lub kliknij z wciśniętym klawiszem Ctrl) na request.
- Kliknij „Kopiuj” → Kopiuj jako cURL
komentarze: 0