Autor: Daniel Stenberg

Tłumaczenie: Rafał Machtyl

Tytuł oryginału: Using cURL to automate HTTP jobs

URL do oryginału: http://curl.haxx.se/docs/httpscripting.html







Sztuka pisania skrypów z żądaniami HTTP przy użyciu cURL


Treść niniejszego dokumentu zakłada że czytający jest obeznany z sieciami komputerowymi i HTML.

Możliwość pisania skryptów jest nieodzowna w dobrym systemie operacyjnym. Unix, zawdzięcza swoją wysoką pozycję właśnie dzięki możliwości stosowania skryptów powłoki i rozmaitych narzędzi do wykonywania rożnych zautomatyzowanych poleceń i skryptów.

Rosnąca ilość aplikacji opartych na sieci uczyniła "Skryptowanie HTTP" coraz częściej wymaganą i poszukiwaną umiejętnością. Zdolność do zupełnie automatycznego pozyskiwania informacji z sieci, imitacja użytkownikow, wysyłanie żądań lub danych do serwerów są ważnymi zadaniami w dzisiejszych czasach.

Curl jest narzędziem linii poleceń wykorzystywanym do wszelkich manipulacji URL i transferów danych, lecz ten dokument skupia się jedynie na wykorzystywaniu żądań HTTP dla zabawy i zysku. Zakładam ze wiesz jak korzystać z wywolań 'curl --help' lub 'curl --manual' by uzyskać podstawowe informacje.

Curl nie zostało napisane by zrobić za ciebie wszystko. Curl wykonuje żądania, pobiera i wysyła dane, wysyła dane, uzyskując w zamian informacje. Prawdopodobnie musisz skleić te wszystkie czynności przy pomocy jakiegoś języka skryptowego lub powtarzanymi wywołaniami z klawiatury.


1. Protokół HTTP

HTTP to protokół używany do przechwytywania danych z serwerów. Jest bardzo prostym protokołem zbudowanym na podstawie TCP/IP. Protokół ten zezwala również na wysyłanie informacji do serwera od klienta przy użyciu kilku różnych metod opisanych w tym dokumencie.

HTTP jest zwyczajnymi liniami tekstu kodowanego w ASCII, wysyłanymi przez klienta do serwera by zażądać szczególnej akcji. W odpowiedzi serwer wysyła najpierw kilka linii tekstu zanim rozpocznie wysyłanie właściwej zawartości żądania.

Użycie opcji curl -v spowoduje wyświetlenie wszystkich komend jakie curl wysyła do serwera, jak również kilka innych tekstów informacyjnych. Opcja -v jest jedną z bardziej użytecznych opcji przy odpluskwianiu, lub nawet zrozumieniu interakcji curl <-> serwer.


2. URL

The Uniform Resource Locator, co w polskim tłumaczeniu oznacza ujednolicony format adresowania zasobów, czyli adres jakiejś konkretnej informacji w internecie. Znasz je, napewno widziałeś adresy URL takie jak http://curl.haxx.se lub https://twojbank.pl milion razy.


3. Uzyskanie Strony (GET)

Najprostszym i najczęstszym żądaniem/operacją dokonywaną przy użyciu HTTP jest właśnie pozyskiwanie URL. URL może odnosć się do strony internetowej, jak również obrazka lub pliku. Klient wydaje polecenie GET do serwera i otrzymuje dokument uwzględniony w żądaniu. Gdy wpiszemy w linii komend:

curl http://curl.haxx.se

Otrzymamy stronę internetową na terminalu. Cały dokument HTML znajdujący się pod wskazanym URL.

Wszystkie odpowiedzi HTTP serwera zawierają zestaw nagłówków, które normalnie są ukryte. Użyj opcji curl -i by wyświetlić je razem z resztą dokumentu. Możesz również zażądać od serwera TYLKO nagłówków dzięki opcji -I (co pozwoli curl wydać żądanie HEAD).


4. Formularze

Formularze są głównym sposobem by umieścić w dokumencie HTML pola w które użytkownik może wpisać dane, a następnie za pomocą przycisku 'OK' lub 'Submit' przesłać te dane do serwera. Następnie serwer na podstawie otrzymanych danych podejmuje decyzję co robić dalej. Czyli na przykład użyć wpisanych słów do przeszukiwania bazy danych, lub dodać jakąś informację do systemu śledzenia pluskiew (bug track), czy też wyświetlić podany adres na mapie, albo użyć podane informacje jako dane dla monitu logowania by zweryfikować czy użytkownik ma dostęp do danych które chce zobaczyć.

Oczywiście na serwerze musi działać odpowiedni program, który odpowiednio obsłuży dane które wysyłasz.


4.1 GET

Formularz korzystający z metody GET w dokumencie HTML może wyglądać tak:

<form method="GET" action="junk.cgi">
<input type=text name="birthyear">
<input type=submit name=press value="OK">
</form>

W twojej ulubionej przeglądarce ten formularz ukaże się jako pole tekstowe do wypełnienia i przycisku z etykietą "OK". Jeżeli wpiszesz '1905' i nacisniesz przycisk OK, twoja przeglądarka utworzy z danych formularza nowy adres URL. Adres: "junk.cgi?birthyear=1905&press=OK" zostanie dodany do poprzedniego URL.

Jeżeli formularz pochodził ze strony "www.hotmail.com/when/birth.html", to następna strona którą pobierze twoja przeglądarka będzie miała adres "www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK".

Tak działa większość mechanizmów wyszukiwania.

By za pomocą curl wypełnić formularz korzystający z metody GET, po prostu utwórz oczekiwany adres URL:

curl "www.hotmail.com/when/junk.cgi?birthyear=1905&press=OK"

4.2 POST

Podczas wysyłania formularza metodą GET, wszystkie dane wpisane w pola tekstowe są widoczne w pasku adresu twojej przeglądarki. Jest to przydatne głównie w sytuacji gdy chcemy dodać do zakładek adres strony wraz z przekazanymi zmiennymi z formularza, ale z oczywistych względów nieodpowiednie gdy w jednym z pól podajemy poufne dane, a zaś formularz z dużą ilością pól wygeneruje bardzo długi i nieczytelny URL.

W tym przpadku protokół HTTP oferuje metodę POST. Przy użyciu tej metody dane wprowadzone przez klienta są przesyłane poza adresem URL, co sprawia że nie są widoczne w polu adresu przeglądarki.

Formularz taki jest bardzo podobny do tego, który korzystał z poprzedniej metody:

<form method="POST" action="junk.cgi">
<input type=text name="birthyear">
<input type=submit name=press value=" OK ">
</form>

Więc by użyć curl do wypełnienia takiego formularza tymi samymi danymi co poprzednio, mogli byśmy zrobić to tak:

curl -d "birthyear=1905&press=%20OK%20" www.hotmail.com/when/junk.cgi

Ten rodzaj POST użyje Content-Type application/x-www-form-urlencoded, co jest najczęściej używaną metodą POST.

Dane, które wysyłasz do serwera MUSZĄ być odpowiednio zakodowane, curl nie zrobi tego za ciebie. Na przykład, jeżeli chcesz by wysyłane dane zawierały spacje, musisz zastąpić je %20 etc. Nie zastosowanie się do tej zasady naogół powoduje pomieszanie i ogólnie mówiąc niepoprawny odbiór danych przez serwer.

Ostatnie wersje curl są w stanie zakodować dane POST do url:

curl --data-urlencode "name=I am Daniel" www.example.com

4.3 File Upload POST

Pod koniec 1995 roku zdefiniowano dodatkowy sposób by przesyłać dane przez HTTP. Sposób ten udokumentowano w opisie standardu RFC 1867, toteż metodę tą nazywa się czasami RFC1867-posting.

Metodę tą zaprojektowano głównie w celu ulepszenia obsługi przesyłania plików do serwera. Formularz, którry zezwala użytkownikowi na wysyłanie plików może mieć taką postać w HTML:

<form method="POST" enctype='multipart/form-data' action="upload.cgi">
<input type=file name=upload>
<input type=submit name=press value="OK">
</form>

Ten formularz wyraźnie określa że dane które mają zostać przesłane mają typ zawartości (Content-Type) multipart/form-data.

By wwysłać powyższy formularz z poziomu curl wpisz następujące polecenie:

curl -F upload=@localfilename -F press=OK [URL]

4.4 Ukryte Pola

Aplikacje oparte o HTML by przekazywać informacje między stronami korzystają w większości przypadków z ukrytych pól formularza. Ukryte pola są wypełnionymi, nie widocznymi dla użytkownika polami formularza i przesyłane w taki sam sposób jak wszystkie pozostałe pola.

Przykładowy formularz z jednym polem widocznym, jednym ukrytym i przyciskiem submit może wyglądać tak:

<form method="POST" action="foobar.cgi">
<input type=text name="birthyear">
<input type=hidden name="person" value="daniel">
<input type=submit name=press value="OK">
</form>

By wysłać to przez curl, nie musisz się zastanawiać czy pola są ukryte czy nie. Dla curl wszystkie są takie same:

curl -d "birthyear=1905&press=OK&person=daniel" [URL]

4.5 Jak Sprawdzić Zawartość Danych POST

Gdy masz zamiar użyć curl zamiast przeglądarki do wypełnienia formularza, konieczne jest wysyłanie danych POST dokładnie w taki sam sposób w jaki robi to twoja przeglądarka.

Prostym sposobem by zobaczyć te dane jest zapisanie na twardy dysk dokumentu HTML z formularzem, zamiana parametru 'method' na GET, i wciśnięcie przycisku wysyłania (można także zmienić URL parametru 'action').

Otrzymasz wtedy dane dołączone do URL, oddzielone znakiem '?' tak samo jak w przypadku formularzy GET.


5. PUT

Prawdopodobnie najlepszym sposobem na wysyłanie danych do serwera HTTP jest użycie PUT. Również w tym przypadku na serwerze konieczna jest obecność programu lub skryptu który potrafi odebrać strumień danych HTTP PUT.

Umieszczenie pliku na serwerze HTTP za pomocą curl:

curl -T uploadfile www.uploadhttp.com/receive.cgi



6. Uwierzytelnianie HTTP

Uwierzytelnianie HTTP to możliwość przekazania do serwera swojej nazwy użytkownika i hasła by mógł zweryfikować czy dany użytkownik ma uprawnienia wymagane do spełnienia żądania. Standardowa autentykacja używana w HTTP (która jest również domyślną w curl) jest oparta o *plain* *text*, co oznacza że przekazuje nazwę użytkownika i hasło odrobinę zamaskowane, więc nadal w pełni czytelne dla każdego kto przechwyci pakiety na trasie między tobą a serwerem.

By kazać curl użyć nazwy użytkownika i hasła do autentykacji:

curl -u name:password www.secrets.com

Strona może wymagać innej metody autentyfikacji (sprawdź nagłówki zwrócone przez serwer)i następnie wybierz z opcji: --ntlm, --digest, --negotiate lub nawet --anyauth odpowiednią dla ciebie.

Czasami twój dostęp do HTTP jest możliwy jedynie przez użycie HTTP proxy. Co zdaje się być szczególnie powszechne w różnych firmach. HTTP proxy może wymagać swojej własnej nazwy użytkownika i hasła by zezwolić użytkownikowi na dostęp do internetu. By określić to za pomocą curl, zastosuj coś takiego:

curl -U proxyuser:proxypassword curl.haxx.se

Jeżeli twój proxy wymaga by autentykacja odbyła się przy użyciu metody NTLM, użyj opcji --proxy-ntlm, w przypadku Digest zastosuj --proxy-digest.

Jeżeli użyjesz jednej z opcji operującej na nazwie użytkownika+haśle bez podania hasła, curl zarząda hasła interaktywnie.

Zauważ że gdy program jest uruchomiony, jego parametry są możliwe do odczytania z listy aktywnych procesów systemu. Toteż inni użytkownicy mają możliwość podejrzenia twoich haseł jeżeli przekażesz je jako opcje w formie zwykłego tekstu. Są jednak sposoby by to obejść.

Wiedza o tym jak działa autentykacja HTTP jest nic nie warta, gdyż bardzo wiele stron nie stosuje tego rozwiązania gdy zapewniają loginy etc. Zobacz zamieszczony poniżej rozdział Web Login by poznać więcej szczegółów.


7. Polecający (Referer)

Żądanie HTTP może zawierać pole 'referer', które może być użyte by określić z jakiego URL klient został pokierowany by uzyskać dany zasób. Niektóre programy/skrypty sprawdzają wartość pola 'referer' zawartego w żądaniu by określić czy nadeszło z zewnętrznej strony, czy też z nieznanej strony. Chociaż głupotą jest sprawdzanie czegoś tak łatwo podrabialnego, wiele skryptów wciąż to robi. Używając curl możesz wstawić co tylko zechcesz w pole 'referer', czyli ułatwić sobie możliwość by oszukać serwer i nakłonić do obsługi twojego żądania.

W ten sposób curl wypełnia pole 'referer':

curl -e http://curl.haxx.se daniel.haxx.se


8. User Agent

Wszystkie żądania HTTP mogą ustawiać bardzo podobne do pola referer, pole User-Agent. Pole to określa jaki przedstawiciel użytkownika (ang. user agent) (klient) został użyty. Wiele aplikacji korzysta z tej informacji by zadecydować w jaki sposób wyświetlać strony. Głupi programiści sieciowi próbują tworzyć różne wersje stron dla użytkowników różnych przeglądarek by wyglądały możliwie jak najlepiej w poszczególnych przeglądarkach. Używają też zazwyczaj różnych rodzajów javascript, vbscript etc.

Z czasem przekonasz się że uzyskiwanie strony przez curl nie zwraca takiej samej strony, jak w przypadku otwarcia jej przeglądarką. Bedzie to odpowiedni moment na ustawienie pola User Agent by serwer myślał że jesteś jedną z tych przeglądarek.

Aby curl udawało Internet Explorer pod kontrolą Windows 2000:

curl -A "Mozilla/4.0 (compatible;MSIE 5.01; Windows NT 5.0)" [URL]

Albo czemu by nie zaimitować Netscape 4.73 pod kontrolą Linux (P III):

curl -A "Mozilla/4.73 [en] (X11; U; Linux 2.2.15 i686)" [URL]


9. Przekierowania

Gdy żądamy od serwera jakiegoś zasobu, odpowiedź serwera może zawierać wskazówkę określającą gdie przeklądarka powinna się udać by odnaleźć tą stronę, lub nową stronę z nowo wygenerowaną zawartością. Nagłówek, który przekierowuje przeglądarke to Location:.

Curl domyślnie nie podąża za nagłówkami Location:, więc po prostu wyświetli takie strony w taki sam sposób jak wszystkie inne odpowiedzi HTTP. Oczywiście istnieje opcja umożliwiająca podążanie za odnośnikami z nagłówków Location:.

W tym przypadku curl będzie podążało za Location:

curl -L www.sitethatredirects.com

Jeśli masz zamiar użyć curl do wysłania danych POST na stronę, która niezwłocznie przekierowuje cię na następną stronę, możesz bez obaw użyć jednocześnie opcji -L i -d/-F. Curl zastosuje metodę POST tylko dla pierwszego żądania, a następnie powróci do GET w następnych operacjach.


10. Cookies

Sposobem w jaki przeglądarki kontrolują status i preferencje użytkownika jest użycie cookies (ciasteczka). Cookies to po prostu nazwy z przypisaną im treścią. Cookies są wysyłane przez serwer do klienta. Serwer informuje klienta pod jaką ścieżkę (path) i nazwę hosta, mają zostać odesłane cookies. Serwer wysyła również datę wygaśnięcia cookies i kilka innych właściwości.

Gdy klient komunikuje się z serwerem korzystając z nazwy hosta i ścieżki zachowanej w uprzednio odebranym cookie, klient odsyła cookies i ich treść do serwera, o ile oczywiście ich ważność nie wygasła.

Wiele aplikacji i serwerów używa tej metody by połączyć serię żądań w jedną logiczną sesję. By wykorzystać curl w takich przypadkach, musimy mieć możliwość zapisywania i wysyłania cookies w sposób w jaki oczekuje tego aplikacja. Czyli dokładnie w taki sam sposób w jaki robi to przeglądarka.

Najprostszym sposobem na wysłanie kilku cookies do serwera podczas "otwierania" strony przez curl jest dodanie ich do linii poleceń np. tak:

curl -b "name=Daniel" www.cookiesite.com

Cookies są przesyłane jako zwyczajne nagłówki HTTP. Jest to korzystne, gdyż pozwala curl zapisywać cookies, zapisując po prostu nagłówki. By curl zapisało cookies użyj opcji -D, na przykład tak:

curl -D headers_and_cookies www.cookiesite.com

(Zwróć uwagę że opcja -c opisana poniżej jest lepszym sposobem by przechowywać cookies.)

Curl posiada wbudowany, w pełni funkcjonalny silnik parsowania cookies, który przydaje się gdy chcesz ponownie połączyć się z serwerem i użyć cookies zachowane z poprzedniego połączenia (bądź też wykonane własnoręcznie by ogłupić serwer by uwiezrył że miałeś poprzednie połączenie). By wykorzystać uprzednio zachowane cookies, uruchom curl w ten sposób:

curl -b stored_cookies_in_file www.cookiesite.com

Działanie "ciasteczkowego silnika" następuje gdy używasz curl z opcją -b. Jeżeli chcesz by curl jedynie zrozumiało otrzymane cookies, użyj -b z nazwą nie istniejącego pliku. Przykładowo, gdy chcesz by curl jedynie przechwyciło cookies ze strony, a następnie podążyło za przekierowaniem (i ewentualnie odesłało otrzymane cookies), zrób to tak:

curl -b nada -L www.cookiesite.com

Curl jest zdolne by odczytywać i zapisywać pliki cookie które używają pliku w formacie, w jakim obsługują je Netscape i Mozilla. Jest to wygodne rozwiązanie w przypadku gdy chcemy dzielić cookies między przeglądarkami a automatycznymi skryptami. Przełącznik -b automatycznie wykrywa czy podany plik z cookies jest właśnie takim plikiem i przetwarza go, zaś w przypadku gdy użyjemy opcji -c/--cookie-jar, curl utworzy nowy plik podczas kończenia operacji:

curl -b cookies.txt -c newcookies.txt www.cookiesite.com


11. HTTPS

Jest kilka sposobów na zabezpieczenie transferu HTTP. Najczęściej używanym protokołem do tego celu jest HTTPS, czyli HTTP oparte o SSL. SSL szyfruje dane wysyłane i odbierane przez sieć, co zmniejsza szanse atakujących sieć, na przechwycenie poufnych informacji.

SSL (bądź też TLS, jak nazwano najnowszą wersję tego standardu) oferuje masę zaawansowanych funkcji koniecznych do tych wszystkich szyfrowań i infrastruktury mechanizmów kluczy wymaganych do szyfrowania HTTP.

Curl wspiera odbiór szyfrowanych danych dzięki swobodnie (darmowo) dostępnym bibliotekom OpenSSL. By pobrać stronę z serwera HTTPS po prostu uruchom curl w ten sposób:

curl https://that.secure.server.com

11.1 Certyfikaty

W świecie HTTPS, używa się certyfikatów by udowodnić że jesteś tym za kogo się podajesz, łącznie z normalnymi hasłami. Curl wspiera certyfikaty klienta. Wszystkie certyfikaty są zablokowane hasłem, które musisz podać przed użyciem certyfikatu przez curl. Hasło może zostać określone w linii poleceń, lub podane interaktywnie gdy zapyta o nie curl. Certyfikatów na serwerze HTTPS za pomocą curl można użyć tak:

curl -E mycert.pem https://that.secure.server.com

Curl stara się również zweryfikować czy serwer jest tym za kogo się podaje, porównując certyfikat serwera z lokalnie przechowywanymi podpisami certyfikatów (CA). Niepomyślna weryfikacja spowoduje że curl odmówi połaczenia. Zastosowanie przełącznika -k spowoduje ignorowanie przez curl niepomyślnej weryfikacji.

Więcej na temat sprawdzania certyfikatów oraz ich podpisów przeczytasz w dokumencie SSLCERTS dostępnym tu:

http://curl.haxx.se/docs/sslcerts.html


12. Żądania niestandardowe

Robiąc "fantazyjne" rzeczy, możliwe że zajdzie potrzeba dodania bądź modyfikacji poszczególnych elementów żądania curl.

Na przykład, możesz zmienić żądanie POST na PROPFIND i wysłać dane jako "Content_Type: text/xml" (zamiast domyślnego Content-Type) w taki sposób:

curl -d "<xml>" -H "Content-Type: text/xml" -X PROPFIND url.com

Możesz usunąć domyślny nagłówek dołanczając w żądaniu nagłówek z nieprzypisaną zawartością. Przykładowo możesz zruinować zapytanie odcinając zawartość nagłówka Host:

curl -H "Host:" http://mysite.com

W ten sam sposób możesz dodawać dowolne nagłówki. Twój serwer może wymagać nagłoówka "Destination:", możesz go dodać:

curl -H "Destination: http://moo.com/nowhere" http://url.com


13. Web Login

Fakt iż procedura nie jest oparta jedynie o "czyste" HTTP, wciąż sprawia wielu ludziom problemy. W tym rozdziale zostanie przedstawione w ogromnym uogólnieniu działanie wszystkich formularzy logowania i jak zalogować się za ich pomocą przy użyciu curl.

Należy zauważyć że by robić to poprawnie w zautomatyzowanym stylu, zapewne nie obędzie się bez skryptów i wielokrotnych wywołań curl etc.

Po pierwsze, serwery używają głównie cookies by wyśledzić zalogowany status klienta, więc konieczne będzie przechwycenie cookies, które zostaną do ciebie wysłane w odpowiedzi. Następnie, wiele stron ustawia specjalny cookie na ich stronie logowania (by upewnić się że znalazłeś się tam poprzez stronę logowania) więc pierwsze co powinieneś zrobić to pobrać stronę z formularzem logowania, by przechwycić ustawiane na niej cookies.

Niektóre systemy logowania korzystają z różnorodnych kodów javascript i czasmi taki kod jest używany do ustawiania bądź modyfikacji zawartości cookies. Możliwe że robią to by zapobiegać programowym logowaniom, tak samo jak ten podręcznik opisuje jak... W każdym razie, jeżeli czytanie kodu nie wystarcza ci by powtórzyć to zachowanie ręcznie, przechwytywanie żądań HTTP wysyłanych/odbieranych przez twoje przeglądarki i analizowanie przesyłanych cookies jest zazwyczaj praktyczną metodą by obejść potrzeby javasript.

W aktualnie używanym tagu <form> stosowanym do logowania, wiele stron wypełnia losowo generowane sesje, lub w innym wypadku potajemnie generowane ukryte tagi i pierwsze co możesz potrzebować to przechwycenie kodu HTML używanego do formularza logowania, a następnie wydobyć wszystkie ukryte pola by mieć możliwość skonstruowania odpowiednich danych POST wysyłanych przy logowaniu. Pamiętaj że zawartość tych danych musi być odpowiednio zakodowana (URL encoding), podczas wysyłania w zwykłym POST.


14. Odpluskwianie

Wiele razy, gdy uruchamiasz curl na jakiejś stronie zauważasz że strona nie odpowiada na twoje żądanie curl tak samo jak odpowiada na żądanie przeglądarki.

W tym momencie musisz postarać się by twoje żądania bardziej podobne do tych wysyłanych przez przeglądarkę:

* Skorzystaj z opcji --trace--ascii do przechowywania szczegółowych logów pomocnych przy analizie i lepszym zrozumieniu.

* Upewnij się czy sprawdziłeś wszystkie cookies i używasz ich gdy są wymagane (odczytywanie -b i zapisywanie -c)

* Przypisz zmiennej USER-AGENT wartość zgodną z aktualną wersją jednej z popularnych przeglądarek

* Ustaw polecającego w ten sm sposób co przeglądarka

* Jeżeli używasz POST, upewnij się że wysyłasz wszystkie pola i w tej samej kolejności jak zrobiła by to przeglądarka.

Barzo pomocnym narzędziem, by upewnić się że robisz wszystko jak należy jest LiveHTTPHeader które pozwala analizować wysyłane/odbierane przez Mozilla/Firefox nagłówki (nawet te korzystające z HTTPS).


15. Literatura

RFC 2616 ten dokument musisz koniecznie przeczytać jeżeli chcesz dogłębnie zrozumieć protokół HTTP.

RFC 2396 wyjaśnia składnię URL.

RFC 2109 definiuje jak powinny działać cookies.

RFC 1867 definiuje wysyłanie plików przez HTTP pzry użyciu POST.

http://openssl.org jest stroną domową projektu OpenSSL

http://curl.haxx.se jest stroną domową projektu cURL.




Free web hostingWeb hosting