Aby dobrze zrozumieć jak wygląda połączenie "od środka" przygotowaliśmy w poprzednim artykule dwa pliki - server.php i client.php. W tym tekście omówimy zasadę ich działania oraz ogólną procedurę połączenia po protokole HTTP. Jest to ważne, aby to dokładnie zrozumieć, gdyż bez znajomości tej podstawowej sprawy dalsza zabawa z cURL-em byłaby bezcelowa. Oczywiście bylibyśmy w stanie wykonać połączenie i je wykorzystać, ale byłaby to wiedza "na sucho". Zrozumienie działania "od podstaw" pozwoli nam na o wiele głębszą zabawę z biblioteką cURL.
Jak wygląda komunikacja z serwerem?
Wchodząc na daną stronę internetową poprzez protokół HTTP, przeglądarka wysyła na serwer, który udostępnia stronę nagłówek (header) z żądaniem dotyczący pobrania jej zawartości. W nagłówku tym przeglądarka wysyła serwerowi kilka informacji o sobie, podaje np. swoją nazwę, swoją wersję, czy też wartość plików cookie, które mamy zapisane dla danej strony. Wszystkie te informacje wysyłane są na serwer w nagłówku. Serwer następnie otrzymuje taki nagłówek i wedle życzenia odpowiada na niego. Odpowiedź taka może być różna. Jeśli strona, o którą prosimy istnieje na serwerze, w odpowiedzi serwer wysyła tym razem swój nagłówek z kodem odpowiedzi, w tym przypadku 200 OK, oznaczający, że strona została odnaleziona.
Wraz z nagłówkiem zwracana jest też do przeglądarki treść strony (body). Jeśli jednak strona nie zostanie odnaleziona, serwer może odesłać nam kod np. 404 Not Found, oznaczający, że zasób, do którego się odwołujemy nie istnieje. Możemy też dostać odpowiedź z kodem z zakresu 3xx, które to kody informują o przekierowaniach i zmianie adresu danej strony. Wszystkie te informacje przesyłane są w nagłówkach pomiędzy stroną (serwerem), a przeglądarką (klientem) na zasadzie:
1. żądanie (request) >>
2. << odpowiedź (response)
Obrazuje to ta grafika:
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj8KUigfE2WXIMsV7w0ekPM-GlXhVFDA2mMfS6pRwJDCuWvC1G-sm0UJsu3o5IHHCLQvF_7Jq4JoOfU2Rjidpu0pWds8NS-mMmUSv9sjSY8OzToJqdUGGnHnx5Z4UYa1TXwOuJ0vBYjzWA/s1600/http_diagram.png)
Wiemy już zatem, że komunikacja taka odbywa się w obie strony za pomocą nagłówków HTTP.
Co jednak dokładnie zawierają w sobie takie nagłówki? Pierwszą i najważniejszą rzeczą jest kod odpowiedzi HTTP. Kod taki jest przesyłany na pierwszym miejscu nagłówka, a jego wartość informuje przeglądarkę o statusie żądania.
Kody te dzielą się na 5 kategorii:
- kody 1xx (np. 110 Connection Timed Out) - są to kody informacyjne
- kody 2xx (np. 200 OK) - są to kody powodzenia
- kody 3xx (np. 301 Moved Permamently) - informują o przekierowaniach
- kody 4xx (np. 404 Not Found) - są kodami błędu po stronie klienta
- kody 5xx (np. 502 Bad Gateway) - są to wewnętrzne błędy serwera
Pełną listę kodów znaleźć można np. tutaj:
http://pl.wikipedia.org/wiki/Kod_odpowiedzi_HTTP
Poza kodem odpowiedzi w nagłówkach przesyłane są oczywiście dodatkowe dane.
Przykładowe nagłówki otrzymane w odpowiedzi od serwera wyglądać mogą np. tak:
[code]
HTTP/1.1 200 OK
Date: Wed, 20 May 2015 17:19:37 GMT
Server: Apache/2.4.9 (Win64) PHP/5.5.12
Set-Cookie: PHPSESSID=ap0a54qaoafbarksjj48i279n1; path=/
Content-Length: 4174
Content-Type: text/html
[/code]
Co oznaczają te informacje?
[code]
HTTP/1.1 200 OK - nazwa protokołu i kod odpowiedzi serwera,
Date: Wed, 20 May 2015 17:19:37 GMT - aktualny czas na serwerze,
Server: Apache/2.4.9 (Win64) PHP/5.5.12 - nazwa oprogramowania serwera,
Set-Cookie: PHPSESSID=ap0a54qaoafbarksjj48i279n1; path=/ - żadanie ustawienia cookie PHPSESSID o wartości ap0a54qaoafbarksjj48i279n1,
Content-Length: 4174 - długość zwracanej zawartości
Content-Type: text/html - typ zwracanej zawartości, w tym przypadku dokument HTML
[/code]
To oczywiście tylko kilka z możliwych nagłówków, pełną ich listę znaleźć można np. tutaj:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
lub tutaj:
http://pl.wikipedia.org/wiki/Lista_nag%C5%82%C3%B3wk%C3%B3w_HTTP
Analogicznie, przeglądarka może wysyłać swoje nagłówki na serwer, np.:
[code]
GET /2015/05/php-curl-podstawy-2-naglowki-http-i-pierwsze-polaczenie-przez-curl.html HTTP/1.1
Host: phpmajster.blogspot.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.10) Gecko/20050717 Firefox/1.0.6
Accept-Language: pl, en-us;q=0.7
Cookie: cookie1=wartość1; cookie2=wartość2
[/code]
Nagłówki takie wysłane przez przeglądarkę do serwera mówią serwerowi o:
[code] // najpierw żądaniu pobrania danego zasobu metodą GET:
GET /2015/05/php-curl-podstawy-2-naglowki-http-i-pierwsze-polaczenie-przez-curl.html HTTP/1.1
Host: phpmajster.blogspot.com
User-Agent: Mozilla/5.0 (X11; U; Linux i686; pl-PL; rv:1.7.10) Gecko/20050717 Firefox/1.0.6 - nazwie przeglądarki, z jakiej następuje żądanie,
Accept-Language: pl, en-us;q=0.7 - preferowanych przez przeglądarkę językach dla zwracanych treści,
Cookie: cookie1=wartość1; cookie2=wartość2 - wartości ciasteczek ustawionych w przeglądarce dla tej domeny
[/code]
Bardzo obszerny tutorial odnośnie nagłówków HTTP znajdziecie np. tutaj:
http://code.tutsplus.com/tutorials/http-headers-for-dummies--net-8039
Jak zatem działa cURL?
Można sobie wyobrazić, choć jest to lekko błędne porównanie - że cURL jest taką wewnętrzną, udawaną przeglądarką, która komunikować będzie się z serwerem tak jak zwykła przeglądarka.Oczywiście porównanie to odnosi się do protokołu HTTP - sam cURL nie ogranicza się jedynie do tego jednego protokołu.
Skoro więc cURL działa na takiej zasadzie, to znaczy to, że potrafi wysyłać i odbierać nagłówki, oraz wszystkie zwracane żadania. Skoro potrafi wysyłać i odbierać to oczywistym jest, że pozwala także na dowolną modyfikację tych danych. Za pomocą cURL-a możemy więc wysyłać dowolne, spreparowane przez siebie nagłówki, podszyć się pod dowolną przeglądarkę, wysłać jakie tylko chcemy ciasteczka, czy żadania POST. Możliwości są ogromne - protokół HTTP to tylko jeden z wielu protokołów przez niego obsługiwanych. Cytując oficjalną stronę biblioteki:
curl is a command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMTP, SMTPS, Telnet and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, HTTP/2, cookies, user+password authentication (Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos), file transfer resume, proxy tunneling and more.
Wchodząc z przeglądarki na ten plik, np. poprzez wpisanie w pasku:
[code]http://localhost/server.php[/code]
zobaczymy póki co pustą listę zmiennych oraz wszystkie nagłówki pobrane przez PHP jakie wysłała do server.php nasza przeglądarka.
Spróbujmy jednak teraz wpisać taki adres:
[code]http://localhost/server.php?a=hello&b=world[/code]
W tablicy $_GET tym razem pojawią się nam dwie zmienne: $a i $b.
To tylko oczywiście przykład, gdyż niczego to nam jeszcze nie pokazuje.
Zabawa zacznie się w pliku client.php.
[code]http://localhost/client.php[/code]
O ile dobrze ustawiliśmy adres do pliku server.php w zmiennej:
[code]$url_to_server = 'http://localhost/server.php';[/code]
To powinno nam się wyświetlić takie oto okno:
(kliknij, aby powiększyć)
Pole oznaczone jako (1) wyświetla wszystkie dane pobrane przez funkcję:
[code]curl_getinfo();[/code]
Funkcja ta zwraca wszystkie informacje o danym stanie połączenia. Podana bez parametrów zwraca wszystkie informacje w postaci tablicy. Możemy jednak określić jaki parametr nas interesuje, podając go w argumencie, np:
[code] $http_status = curl_getinfo(CURLINFO_HTTP_CODE);[/code]
zwróci ostatni status odpowiedzi od serwera.
Pełną listę parametrów jakie funkcja może przyjąć znajdziemy tutaj: http://php.net/manual/en/function.curl-getinfo.php
Po lewej (4) znajduje się blok zatytułowany RESPONSE FROM http://localhost/server.php.
Co się w nim znajduje? Otoż skrypt w pliku client.php za pomocą cURL-a połączył się z adresem http://localhost/server.php, wysłał mu swoje nagłówki, a następnie od pliku server.php odebrał nagłówki odpowiedzi i zawartość pożądanej strony. Otrzymana zawartość jak i zwrócone nagłówki zostały następnie wyświetlone w tym bloku (zwrócone nagłówki znajdują się po prawej [3]), za pomocą zwykłej funkcji echo().
Zauważmy, że zwrócona zawartość została turaj zwrócona w formie takiej, w jakiej wywołał ją cURL, a nie przeglądarka.
Aby zauważyć różnicę spójrzmy w kolumnę Headers i w nagłówek User-Agent.
Nie znajduje się już w nim nazwa naszej przeglądarki, a nazwa fake browser, wysłana "oszukańczo" w nagłówku przez cURL.
Zmodyfikujmy teraz lekko zmienną $url_to_server, wpiszmy tam:
[code]$url_to_server = 'http://localhost/server.php?who_wants_me=curl';[/code]
W tablicy $_GET zwróconego żądania pojawiła się nam zmienna $who_wants_me o wartości curl wysłana przez cURL. W następnych artykułach prześlemy tam również ciasteczka, pliki i zmienne POST, na razie pokazuję jedynie przykład, abyście zrozumieli zasadę działania.
Sesję połączenia poprzez cURL inicjujemy następująco:
[code]$ch = curl_init($url_to_server);[/code]
gdzie:
w naszym przypadku odpowiada to:
[code]$ch = curl_init('http://localhost/server.php');[/code]
Można też pominąć argument z adresem i ustawić go później za pomocą opcji CURLOPT_URL, np:
[code]$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost/server.php');[/code]
Najpierw musimy ustawić w cURL-u kilka kluczowych parametrów.
Jak zostało wspomniane przy okazji ustawiania nagłówka, opcje ustawiamy za pomocą funkcji:
[code]curl_setopt($ch, NAZWA_OPCJI, WARTOŚĆ);[/code]
Ustawmy na początek kilka opcji:
[code]curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);[/code]
Opcja CURLOPT_RETURNTRANSFER ustawiona na 1 mówi cURL-owi, że chcemy otrzymać zwróconą zawartość do jakiej odwołujemy się w połączeniu, w postaci stringa.
[code]curl_setopt($ch, CURLOPT_USERAGENT, 'fake browser');
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com');[/code]
Powyższymi opcjami ustawiamy nagłówki User-Agent i Referer, które wyślemy razem z połączeniem na serwer. Zauważmy, że możemy dowolnie manipulować tymi nagłówkami - stąd też nie polecam nigdy sugerować się w swoich skryptach wartościami pobieranymi od przeglądarki - można je dowolnie podrobić.
Ustawienie natomiast automatycznego REFERERA wymusimy na cURL-u poprzez:
[code]curl_setopt($ch, CURLOPT_AUTOREFERER, 1);[/code]
[code]curl_setopt($ch, CURLOPT_HTTPHEADER, $tablica_z_nagłówkami);[/code]
jako wartość przyjmuje on tablicę z nagłówkami, np.:
[code]
$headers = array(
"User-Agent: Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7",
"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8",
"Accept-Language: pl,en-us;q=0.7,en;q=0.3",
"Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7",
"Keep-Alive: 300",
"Connection: keep-alive"
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);[/code]
[code]
$options = array(CURLOPT_URL => 'http://www.google.com/',
CURLOPT_HEADER => true
);
curl_setopt_array($ch, $options);
[/code]
Warto wiedzieć, że możliwych opcji jest bardzo dużo, pełna ich lista znajduje się tutaj:
http://php.net/manual/en/function.curl-setopt.php
[code]$response_body = curl_exec($ch);[/code]
Do zmiennej $response_body zostanie nam zwrócona cała otrzymana w odpowiedzi zawartość.
Na koniec zamykamy sesję połączenia, służy do tego:
[code]curl_close($ch);[/code]
Jeśli niczego nie pomyliliśmy, powinna nam się wyświetlić odpowiedź z pliku server.php.
Ale czegoś nam tu brakuje - pole [HEADERS] jest puste.
Stało się tak dlatego, iż nie zdefiniowaliśmy opcji odpowiedzialnej za pobranie nagłówków.
Można to zrobić na 3 sposoby:
[code]curl_setopt($ch, CURLOPT_HEADER, 1);[/code]
sprawi, że zwrócony zostanie zarówno nagłówek jak i treść strony, połączone w jeden ciąg;
[code]curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);[/code]
sprawi, że zwrócony zostanie jedynie nagłówek, bez treści strony;
i trzeci, najbardziej tutaj elegancki sposób, który wykorzystamy:
[code]curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerLine");[/code]
definiuje on nazwę naszej własnej funkcji, która odpowiedzialna będzie za przetwarzanie pobranych nagłówków. W naszym przypadku mamy tutaj przygotowaną funkcję headerLine(), która pobierze nam nagłówki do tablicy.
Finalnie nasze połączenie wyglądać więc będzie tak:
[code]<?php
// do tej tablicy odbierzemy nagłówki
$return_headers = [];
// funkcja odbierająca nagłówki
function headerLine($curl, $header_line ) {
$GLOBALS['return_headers'][] = $header_line;
return strlen($header_line);
}
// definiujemy URL do pliku 'server.php'
$url_to_server = 'http://localhost/server.php';
// inicjujemy sesję połączenia
$ch = curl_init($url_to_server);
// ustawiamy nagłówki
$headers = array(
"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8",
"Accept-Language: pl,en-us;q=0.7,en;q=0.3",
"Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7",
"Keep-Alive: 300",
"Connection: keep-alive"
);
// ustawiamy opcje
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // chcemy odebrać dane
curl_setopt($ch, CURLOPT_USERAGENT, 'fake browser'); // ustawiamy własnego user-agenta
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com'); // ustawiamy własnego referera
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // dołączamy nagłówki
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerLine"); // ustawiamy własną funkcję do przetworzenia odbieranego nagłówka
// wykonujemy połączenie
$response_body = curl_exec($ch);
// zamykamy sesję połączenia
curl_close($ch);
?>[/code]
Po wykonaniu kodu, w zmiennej $response_body mamy odebraną treść strony, natomiast w tablicy $return_headers wszystkie odebrane nagłówki.
W naszym pliku client.php jest to wszystko wygodnie wylistowane za pomocą DIV-ów i jeszcze jednej funkcji: getResponseHeaders(), która wyświetla odebrane do tablicy nagłówki, jeśli jednak chcemy wyświetlić dane "na sucho", to możemy zrobić to zwyczajnie przez echo():
[code]echo 'HEADERS: '.implode('<br />', $return_headers);
echo 'BODY: '.$response_body;[/code]
[code]curl_errno($ch);[/code]
Wzbogaćmy więc nasz kod o obsługę wyświetlania ewentualnych błędów:
[code]if (curl_errno($ch)) $errors.= '<h2>Error #' . curl_errno($ch) . ': ' . curl_error($ch).'</h2>';[/code]
- funkcja curl_errno($ch) pobiera numer błędu,
- funkcja curl_error($ch) pobiera treść błędu.
Warto wiedzieć, że opcja::
[code]curl_setopt($ch, CURLOPT_VERBOSE, 1);[/code]
włącza więcej informacji w komunikatach o błędach.
Funkcję odpowiedzialną za obsługę błędów umieszczamy po funkcji curl_exec($ch), nasz kod wyglądać więc będzie tak:
[code]<?php
// do tej tablicy odbierzemy nagłówki
$return_headers = [];
$errors = '';
// funkcja odbierająca nagłówki
function headerLine($curl, $header_line ) {
$GLOBALS['return_headers'][] = $header_line;
return strlen($header_line);
}
// definiujemy URL do pliku 'server.php'
$url_to_server = 'http://localhost/server.php';
// inicjujemy sesję połączenia
$ch = curl_init($url_to_server);
// ustawiamy opcje
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // chcemy odebrać dane
curl_setopt($ch, CURLOPT_USERAGENT, 'fake browser'); // ustawiamy user-agenta
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com'); // ustawiamy referera
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerLine"); // ustawiamy własną funkcję do przetworzenia nagłówka
curl_setopt($ch, CURLOPT_VERBOSE, 1); // dokładniejsze komunikaty o błędach
// wykonujemy połączenie
$response_body = curl_exec($ch);
// pobieramy błąd, jeśli wystąpi
if (curl_errno($ch)) $errors.= '<h2>Error #' . curl_errno($ch) . ': ' . curl_error($ch).'</h2>';
// zamykamy sesję połączenia
curl_close($ch);
// wyświetlamy wszystko na ekran, jeśli chcemy to zrobić po swojemu, w pliku 'client.php' te dane wyświetlane są automatycznie w odpowiednich DIV-ach:
echo $errors.'<br />';
echo 'HEADERS: '.implode('<br />', $return_headers).'<br />';
echo 'BODY: '.$response_body;
?>[/code]
I na koniec mały przykład praktycznego wykorzystania cURL-a - pobranie tytułu najnowszego posta z tego bloga:
[code]<?php
// do tej tablicy odbierzemy nagłówki
$return_headers = [];
$errors = '';
// funkcja odbierająca nagłówki
function headerLine($curl, $header_line ) {
$GLOBALS['return_headers'][] = $header_line;
return strlen($header_line);
}
// url do feeda w formacie JSON
$url_to_server = 'http://phpmajster.blogspot.com/feeds/posts/default?alt=json&max-results=1';
// inicjujemy sesję połączenia
$ch = curl_init($url_to_server);
// ustawiamy opcje
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // chcemy odebrać dane
curl_setopt($ch, CURLOPT_USERAGENT, 'fake browser'); // ustawiamy user-agenta
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com'); // ustawiamy referera
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerLine"); // ustawiamy własną funkcję do przetworzenia nagłówka
// wykonujemy połączenie
$response_body = curl_exec($ch);
// pobieramy błąd, jeśli wystąpi
if (curl_errno($ch)) $errors.= '<h2>Error #' . curl_errno($ch) . ': ' . curl_error($ch).'</h2>';
// zamykamy sesję połączenia
curl_close($ch);
// tytuł pobrany z JSON-a:
$json = json_decode($response_body, true);
echo $json['feed']['entry'][0]['title']['$t'];
?>[/code]
Potrafimy więc już się połączyć, ustawić podstawowe opcje oraz pobrać zwracaną zawartość i nagłówki. Na tym jednocześnie kończymy ten atrykuł, w następnych częściach dowiemy się więcej, m.in. więcej o opcjach, a także o wysyłaniu bardziej złożonych żądań.
Oficjalny, pełny manual biblioteki cURL znajduje się tutaj: http://php.net/manual/en/book.curl.php
curl is a command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, Gopher, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMB, SMTP, SMTPS, Telnet and TFTP. curl supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, HTTP/2, cookies, user+password authentication (Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos), file transfer resume, proxy tunneling and more.
Wracamy do naszego środowiska - server.php
Powróćmy więc teraz do przygotowanych tutaj plików, na których będziemy testować polecenia cURL-a. W pliku server.php napisana jest funkcja, która listuje wszystkie zmienne z następujących PHP-owskich tablic: $_GET, $_POST, $_COOKIE, $_SESSION, $_SERVER, $_ENV, $_REQUEST i $_FILES, a także wszystkie nagłówki otrzymane od przeglądarki/cURL-a.Wchodząc z przeglądarki na ten plik, np. poprzez wpisanie w pasku:
[code]http://localhost/server.php[/code]
zobaczymy póki co pustą listę zmiennych oraz wszystkie nagłówki pobrane przez PHP jakie wysłała do server.php nasza przeglądarka.
Spróbujmy jednak teraz wpisać taki adres:
[code]http://localhost/server.php?a=hello&b=world[/code]
W tablicy $_GET tym razem pojawią się nam dwie zmienne: $a i $b.
To tylko oczywiście przykład, gdyż niczego to nam jeszcze nie pokazuje.
Zabawa zacznie się w pliku client.php.
Informacje o stanie połączenia - curl_getinfo()
Przejdźmy do pliku client.php:[code]http://localhost/client.php[/code]
O ile dobrze ustawiliśmy adres do pliku server.php w zmiennej:
[code]$url_to_server = 'http://localhost/server.php';[/code]
To powinno nam się wyświetlić takie oto okno:
(kliknij, aby powiększyć)
Pole oznaczone jako (1) wyświetla wszystkie dane pobrane przez funkcję:
[code]curl_getinfo();[/code]
Funkcja ta zwraca wszystkie informacje o danym stanie połączenia. Podana bez parametrów zwraca wszystkie informacje w postaci tablicy. Możemy jednak określić jaki parametr nas interesuje, podając go w argumencie, np:
[code] $http_status = curl_getinfo(CURLINFO_HTTP_CODE);[/code]
zwróci ostatni status odpowiedzi od serwera.
Pełną listę parametrów jakie funkcja może przyjąć znajdziemy tutaj: http://php.net/manual/en/function.curl-getinfo.php
Po lewej (4) znajduje się blok zatytułowany RESPONSE FROM http://localhost/server.php.
Co się w nim znajduje? Otoż skrypt w pliku client.php za pomocą cURL-a połączył się z adresem http://localhost/server.php, wysłał mu swoje nagłówki, a następnie od pliku server.php odebrał nagłówki odpowiedzi i zawartość pożądanej strony. Otrzymana zawartość jak i zwrócone nagłówki zostały następnie wyświetlone w tym bloku (zwrócone nagłówki znajdują się po prawej [3]), za pomocą zwykłej funkcji echo().
Zauważmy, że zwrócona zawartość została turaj zwrócona w formie takiej, w jakiej wywołał ją cURL, a nie przeglądarka.
Aby zauważyć różnicę spójrzmy w kolumnę Headers i w nagłówek User-Agent.
Nie znajduje się już w nim nazwa naszej przeglądarki, a nazwa fake browser, wysłana "oszukańczo" w nagłówku przez cURL.
Zmodyfikujmy teraz lekko zmienną $url_to_server, wpiszmy tam:
[code]$url_to_server = 'http://localhost/server.php?who_wants_me=curl';[/code]
W tablicy $_GET zwróconego żądania pojawiła się nam zmienna $who_wants_me o wartości curl wysłana przez cURL. W następnych artykułach prześlemy tam również ciasteczka, pliki i zmienne POST, na razie pokazuję jedynie przykład, abyście zrozumieli zasadę działania.
Połączenie przez cURL - curl_init()
Jeśli już rozumiemy jak to wszystko działa, to pora na rozpoczęcie zabawy.Sesję połączenia poprzez cURL inicjujemy następująco:
[code]$ch = curl_init($url_to_server);[/code]
gdzie:
- $ch - to zwracany zasób/uchwyt sesji naszego połączenia
- $url_to_server - adres połaczenia
w naszym przypadku odpowiada to:
[code]$ch = curl_init('http://localhost/server.php');[/code]
Można też pominąć argument z adresem i ustawić go później za pomocą opcji CURLOPT_URL, np:
[code]$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost/server.php');[/code]
Ustawianie parametrów - curl_setopt()
Po zainicjowaniu sesji połączenia jeszcze nic się nie dzieje.Najpierw musimy ustawić w cURL-u kilka kluczowych parametrów.
Jak zostało wspomniane przy okazji ustawiania nagłówka, opcje ustawiamy za pomocą funkcji:
[code]curl_setopt($ch, NAZWA_OPCJI, WARTOŚĆ);[/code]
Ustawmy na początek kilka opcji:
[code]curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);[/code]
Opcja CURLOPT_RETURNTRANSFER ustawiona na 1 mówi cURL-owi, że chcemy otrzymać zwróconą zawartość do jakiej odwołujemy się w połączeniu, w postaci stringa.
[code]curl_setopt($ch, CURLOPT_USERAGENT, 'fake browser');
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com');[/code]
Powyższymi opcjami ustawiamy nagłówki User-Agent i Referer, które wyślemy razem z połączeniem na serwer. Zauważmy, że możemy dowolnie manipulować tymi nagłówkami - stąd też nie polecam nigdy sugerować się w swoich skryptach wartościami pobieranymi od przeglądarki - można je dowolnie podrobić.
Ustawienie natomiast automatycznego REFERERA wymusimy na cURL-u poprzez:
[code]curl_setopt($ch, CURLOPT_AUTOREFERER, 1);[/code]
Ustawianie dowolnego nagłówka - CURLOPT_HTTPHEADER
Każdy możliwy nagłówek HTTP ustawić możemy za pomocą:[code]curl_setopt($ch, CURLOPT_HTTPHEADER, $tablica_z_nagłówkami);[/code]
jako wartość przyjmuje on tablicę z nagłówkami, np.:
[code]
$headers = array(
"User-Agent: Mozilla/5.0 (X11; U; Linux i686; pl; rv:1.8.1.7) Gecko/20070914 Firefox/2.0.0.7",
"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8",
"Accept-Language: pl,en-us;q=0.7,en;q=0.3",
"Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7",
"Keep-Alive: 300",
"Connection: keep-alive"
);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);[/code]
Ustawianie parametrów z tablicy - curl_setopt_array()
Parametrów nie musimy ustawiać oddzielnie. Możemy to zrobić w tablicy:[code]
$options = array(CURLOPT_URL => 'http://www.google.com/',
CURLOPT_HEADER => true
);
curl_setopt_array($ch, $options);
[/code]
Warto wiedzieć, że możliwych opcji jest bardzo dużo, pełna ich lista znajduje się tutaj:
http://php.net/manual/en/function.curl-setopt.php
Wykonanie połączenia - curl_exec()
Mając ustawione podstawowe opcje, wykonajmy nasze połączenie:[code]$response_body = curl_exec($ch);[/code]
Do zmiennej $response_body zostanie nam zwrócona cała otrzymana w odpowiedzi zawartość.
Na koniec zamykamy sesję połączenia, służy do tego:
[code]curl_close($ch);[/code]
Jeśli niczego nie pomyliliśmy, powinna nam się wyświetlić odpowiedź z pliku server.php.
Ale czegoś nam tu brakuje - pole [HEADERS] jest puste.
Stało się tak dlatego, iż nie zdefiniowaliśmy opcji odpowiedzialnej za pobranie nagłówków.
Można to zrobić na 3 sposoby:
[code]curl_setopt($ch, CURLOPT_HEADER, 1);[/code]
sprawi, że zwrócony zostanie zarówno nagłówek jak i treść strony, połączone w jeden ciąg;
[code]curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);[/code]
sprawi, że zwrócony zostanie jedynie nagłówek, bez treści strony;
i trzeci, najbardziej tutaj elegancki sposób, który wykorzystamy:
[code]curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerLine");[/code]
definiuje on nazwę naszej własnej funkcji, która odpowiedzialna będzie za przetwarzanie pobranych nagłówków. W naszym przypadku mamy tutaj przygotowaną funkcję headerLine(), która pobierze nam nagłówki do tablicy.
Finalnie nasze połączenie wyglądać więc będzie tak:
[code]<?php
// do tej tablicy odbierzemy nagłówki
$return_headers = [];
// funkcja odbierająca nagłówki
function headerLine($curl, $header_line ) {
$GLOBALS['return_headers'][] = $header_line;
return strlen($header_line);
}
// definiujemy URL do pliku 'server.php'
$url_to_server = 'http://localhost/server.php';
// inicjujemy sesję połączenia
$ch = curl_init($url_to_server);
// ustawiamy nagłówki
$headers = array(
"Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8",
"Accept-Language: pl,en-us;q=0.7,en;q=0.3",
"Accept-Charset: ISO-8859-2,utf-8;q=0.7,*;q=0.7",
"Keep-Alive: 300",
"Connection: keep-alive"
);
// ustawiamy opcje
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // chcemy odebrać dane
curl_setopt($ch, CURLOPT_USERAGENT, 'fake browser'); // ustawiamy własnego user-agenta
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com'); // ustawiamy własnego referera
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); // dołączamy nagłówki
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerLine"); // ustawiamy własną funkcję do przetworzenia odbieranego nagłówka
// wykonujemy połączenie
$response_body = curl_exec($ch);
// zamykamy sesję połączenia
curl_close($ch);
?>[/code]
Po wykonaniu kodu, w zmiennej $response_body mamy odebraną treść strony, natomiast w tablicy $return_headers wszystkie odebrane nagłówki.
W naszym pliku client.php jest to wszystko wygodnie wylistowane za pomocą DIV-ów i jeszcze jednej funkcji: getResponseHeaders(), która wyświetla odebrane do tablicy nagłówki, jeśli jednak chcemy wyświetlić dane "na sucho", to możemy zrobić to zwyczajnie przez echo():
[code]echo 'HEADERS: '.implode('<br />', $return_headers);
echo 'BODY: '.$response_body;[/code]
Obsługa błędów - curl_errno() i curl_error()
Biblioteka cURL posiada całą listę kodów błędów, zwracane są one poprzez funkcję:[code]curl_errno($ch);[/code]
Wzbogaćmy więc nasz kod o obsługę wyświetlania ewentualnych błędów:
[code]if (curl_errno($ch)) $errors.= '<h2>Error #' . curl_errno($ch) . ': ' . curl_error($ch).'</h2>';[/code]
- funkcja curl_errno($ch) pobiera numer błędu,
- funkcja curl_error($ch) pobiera treść błędu.
Warto wiedzieć, że opcja::
[code]curl_setopt($ch, CURLOPT_VERBOSE, 1);[/code]
włącza więcej informacji w komunikatach o błędach.
Funkcję odpowiedzialną za obsługę błędów umieszczamy po funkcji curl_exec($ch), nasz kod wyglądać więc będzie tak:
[code]<?php
// do tej tablicy odbierzemy nagłówki
$return_headers = [];
$errors = '';
// funkcja odbierająca nagłówki
function headerLine($curl, $header_line ) {
$GLOBALS['return_headers'][] = $header_line;
return strlen($header_line);
}
// definiujemy URL do pliku 'server.php'
$url_to_server = 'http://localhost/server.php';
// inicjujemy sesję połączenia
$ch = curl_init($url_to_server);
// ustawiamy opcje
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // chcemy odebrać dane
curl_setopt($ch, CURLOPT_USERAGENT, 'fake browser'); // ustawiamy user-agenta
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com'); // ustawiamy referera
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerLine"); // ustawiamy własną funkcję do przetworzenia nagłówka
curl_setopt($ch, CURLOPT_VERBOSE, 1); // dokładniejsze komunikaty o błędach
// wykonujemy połączenie
$response_body = curl_exec($ch);
// pobieramy błąd, jeśli wystąpi
if (curl_errno($ch)) $errors.= '<h2>Error #' . curl_errno($ch) . ': ' . curl_error($ch).'</h2>';
// zamykamy sesję połączenia
curl_close($ch);
// wyświetlamy wszystko na ekran, jeśli chcemy to zrobić po swojemu, w pliku 'client.php' te dane wyświetlane są automatycznie w odpowiednich DIV-ach:
echo $errors.'<br />';
echo 'HEADERS: '.implode('<br />', $return_headers).'<br />';
echo 'BODY: '.$response_body;
?>[/code]
I na koniec mały przykład praktycznego wykorzystania cURL-a - pobranie tytułu najnowszego posta z tego bloga:
[code]<?php
// do tej tablicy odbierzemy nagłówki
$return_headers = [];
$errors = '';
// funkcja odbierająca nagłówki
function headerLine($curl, $header_line ) {
$GLOBALS['return_headers'][] = $header_line;
return strlen($header_line);
}
// url do feeda w formacie JSON
$url_to_server = 'http://phpmajster.blogspot.com/feeds/posts/default?alt=json&max-results=1';
// inicjujemy sesję połączenia
$ch = curl_init($url_to_server);
// ustawiamy opcje
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // chcemy odebrać dane
curl_setopt($ch, CURLOPT_USERAGENT, 'fake browser'); // ustawiamy user-agenta
curl_setopt($ch, CURLOPT_REFERER, 'http://www.google.com'); // ustawiamy referera
curl_setopt($ch, CURLOPT_HEADERFUNCTION, "headerLine"); // ustawiamy własną funkcję do przetworzenia nagłówka
// wykonujemy połączenie
$response_body = curl_exec($ch);
// pobieramy błąd, jeśli wystąpi
if (curl_errno($ch)) $errors.= '<h2>Error #' . curl_errno($ch) . ': ' . curl_error($ch).'</h2>';
// zamykamy sesję połączenia
curl_close($ch);
// tytuł pobrany z JSON-a:
$json = json_decode($response_body, true);
echo $json['feed']['entry'][0]['title']['$t'];
?>[/code]
Potrafimy więc już się połączyć, ustawić podstawowe opcje oraz pobrać zwracaną zawartość i nagłówki. Na tym jednocześnie kończymy ten atrykuł, w następnych częściach dowiemy się więcej, m.in. więcej o opcjach, a także o wysyłaniu bardziej złożonych żądań.
Oficjalny, pełny manual biblioteki cURL znajduje się tutaj: http://php.net/manual/en/book.curl.php
Brak komentarzy:
Prześlij komentarz
Masz sugestię? Znalazłeś błąd? Napisz komentarz! :)