piątek, 29 maja 2015

[SOAP] Podstawy protokołu SOAP i tworzenie prostej usługi sieciowej

TRUE
9082655585334498120
SOAP (Simple Object Access Protocol) to protokół wymiany informacji pomiędzy różnymi hostami i aplikacjami sieciowymi. Jest niezależny od platformy i języka, gdyż wszelka wymiana danych odbywa się za pomocą powszechnie używanego języka XML.
SOAP jest standardem komunikacji pomiędzy potencjalnie nie związanymi ze sobą usługami sieciowymi. Serwer udostępniający usługę sieciową (Web Service) może np. działać pod kontrolą ASP.NET, natomiast aplikacja kliencka może być napisana w PHP, bądż w każdym innym dowolnym języku. Cała wymiana danych odbywa się bowiem poprzez niezależny od platformy język XML.

Jak działa SOAP? Otóż wyobraźmy sobie serwer, który może udostępniać daną usługę, np. podającą aktualną datę na serwerze. Serwer zatem posiada u siebie jakąś funkcję, która takową datę pobiera i może ją udostępnić na zewnątrz. Mając informację o tym jaki jest adres serwera i jak konkretnie taka funkcja się nazywa, aplikacja kliencka może wysłać do serwera żądanie z prośbą o wykonanie tej funkcji na serwerze i zwrócenia wygenerowanych przez nią danych do klienta.

Zarówno żądanie od klienta jak i odpowiedź od serwera wysyłane są za pomocą specjalnie spreparowanego XML-a, nie ma więc znaczenia jaka aplikacja prosi o wykonanie żądania i nie ma też znaczenia jaka aplikacja to żądanie wykona, byleby zwróciła wynik za pomocą języka XML. Serwer SOAP może posiadać oczywiście więcej takich zdefiowanych funkcji i poza podaniem godziny na serwerze może np. posiadać funkcje zwracające na żądanie inne typy danych.

WSDL

Funkcje takie jednak muszą się jakoś nazywać - np. getDate(), getTime(), getSomething() itd.
Klient, który nie wie w jaki sposób poprosić serwer o dane informacje takich informacji nie otrzyma, gdyż najzwyczajniej w świecie nie będzie wiedział jakie funkcje taki serwer oferuje, jakie są ich nazwy i jakie dane zwracają.

Z pomocą przychodzi tutaj specjalny język stworzony właśnie do opisu oferowanych przez daną usługę sieciową, czyli serwer funkcji wraz z opisem rodzaju zwracanych i przyjmowanych przez nie danych. Język ten nazywa się WSDL (Web Services Description Language) i służy klientowi jako źródło informacji o tym co może zaoferować mu dana usługa sieciowa. Jest to tak naprawdę również XML, tyle że o ściśle określonej strukturze. W interesie serwera (usługi sieciowej) jest przygotowanie takiego dokumentu WSDL, bo po co komu udostępnianie jakiś funkcji, skoro nikt nie może z nich skorzystać, gdyż zwyczajnie o nich nie wie.

Komunikacja po HTTP

Informacje pomiędzy serwerem i klientem zazwyczaj przesyłane są po protokole HTTP. Ma to o tyle ciekawą zaletę, że protokół ten prawie nigdy nie jest zablokowany przez zapory sieciowe, co za tym idzie - mamy prawie, że pewność, że przesyłane dane nie utkną gdzieś po drodze na jakimś firewallu, który zablokowałby je, gdyby były wysłane po jakimś dziwnym, niestandardowym porcie.

Zastosowania

Większość szanujących się dużych usługodawców udostępnia swoje usługi za pomocą protokołu SOAP. Robi tak np. Google ze swoim API, robi tak także nasze rodzime (przynajmniej kiedyś) Allegro, które udostępnia swoje API poprzez SOAP, dzięki któremu możemy tworzyć aplikacje pobierające np. informacje o naszych aukcjach, czy kontrahentach.

Zastosowanie SOAP-a jest więc powszechne na świecie i warto byłoby posiadać choćby podstawową wiedzę na temat korzystania z tego protokołu. Nic również nie stoi na przeszkodzie, aby utworzyć swoją własną usługę sieciową za pomocą protokołu SOAP co nawet tutaj uczynimy i zobaczymy, że nie jest to wcale takie trudne jak może się wydawać.

Schemat działania


Na samym początku klient prosi usługę sieciową o przedstawienie wszystkich funkcji jakie ona udostępnia do wykonania i jakie dane one zwracają. Serwer odbiera prośbę i odsyła klientowi dokument WSDL zawierający spis wszystkich takich funkcji wraz z ich nazwami, przyjmowanymi parametrami oraz rodzajem wartości jakie zwracają w wyniku.



W tym momencie klient wie już, że na serwerze dostępna jest funkcja o nazwie np. getTime(), która pobiera aktualny czas na serwerze i zwraca wynik w formacie podanym jako parametr. Zwracana wartość jest zwracana jako ciąg znaków o czym klient zostaje poinformowany za pomocą WSDL.

Funkcja na serwerze może mniej więcej wyglądać tak:
[code]
function getTime($time_format)
{
  return date($time_format);
}
[/code]

Klient wiedząc już teraz, że istnieje taka funkcja, że ma nazwę getTime i że zwraca ona dane jako string, oraz że przyjmuje parametr również w spostaci stringu określający format podania czasu, może poprosić serwer o wykonanie tej funkcji podając jej nazwę i parametr, a następnie odebrać od serwera wynik jej działania, oczekując w odpowiedzi ciągu tekstowego zawierającego godzinę na serwerze:



Jak wiec widzimy, cała procedura polega na wysłaniu do serwera prośby o wykonanie danej funkcji, wykonaniu tej funkcji przez serwer, pobrania i odesłaniu wyniku przez serwer, a następnie odebraniu tego wyniku przez klienta. Z tak odebranymi danymi klient następnie może już robić co chce.


Przykładowa usługa sieciowa

Możemy przetestować działanie jednego z dostępnych publicznie webservice'ów w praktyce, aby zobaczyć jak to wygląda.
Wejdżmy np. na stronę: http://www.ripedev.com/webservices/localtime.asmx  
Usługa tutaj posiada jedną funkcję: LocalTimeByZipCode(), która po podaniu jako parametr kodu pocztowego zwraca czas lokalny w jego lokalizacji.

Jednocześnie możemy przyjrzeć się plikowi WSDL jaki posiada taka usługa:
Do definicji WSDL zawsze dostajemy się poprzez wywołanie:
[code]http://adres_serwera.com/?WSDL[/code]
W tym przypadku wejdżmy na:
http://www.ripedev.com/webservices/localtime.asmx?WSDL
Zobaczymy jak wygląda taka definicja WSDL "od środka". Jak widzimy jest do dokument XML, dość obszerny tak swoją drogą jak na tylko jedną funkcję, ale bez obaw - takich dokumentów nie tworzymy ręcznie, są one generowanie przez serwer SOAP. Tutaj mała uwaga - pisząc dokument WSDL nie mam na myśli fizycznego pliku, gdyż dokument ten jest niejako generowany w locie, nie istnieje on tak naprawdę fizycznie na serwerze.

Tworzymy własny serwer SOAP do testów

Stworzymy teraz swój własny serwer z prostą usługą sieciową, a następnie się z nią połączymy.
Pozwoli to nam zobaczyć jak to wszystko działa od środka. W PHP istnieje kilka implementacji protokołu SOAP, my wybierzemy implementację o nazwie:
[code]nuSOAP[/code]
Jest to prosta w obsłudze biblioteka, która pozwoli nam na bezproblemową pracę z usługami sieciowymi. Instalacja jest prosta, sprowadza się do pobrania biblioteki i zapisania jej w folderze z naszym projektem.

Bibliotekę pobieramy stąd:
http://sourceforge.net/projects/nusoap/

Pobierzmy plik, rozpakujmy, a jego zawartość, czyli folder /lib skopiujmy np. do:
[code]/ścieżka/do/naszego/katalogu/z/www/soap[/code]
tak abyśmy mieli dostęp do projektu, który zaraz stworzymy z adresu:
[code]http://localhost/soap[/code]

Utwórzmy teraz plik index.php w naszym folderze /soap i zaincludujmy w nim pobraną bibliotekę:
[code]
<?php
/* index.php */
require_once("lib/nusoap.php");
?>
[/code]
Jesteśmy już gotowi do pracy z biblioteką nuSOAP.
Jako przykładową funkcję w naszej usłudze stworzymy sobie taką jaką omawialiśmy na przykładzie pobrania czasu z serwera. Nazwiemy ją tak samo - getTime(), a samą usługę sieciową nazwiemy mySOAP.

Utworzenie usługi

Pracę rozpoczynamy od utworzenia obiektu klasy soap_server:
[code]$server = new soap_server();[/code]
Następnie wstępnie konfigurujemy naszą definicję WSDL, robimy to za pomocą:
[code]$server->configureWSDL($service_name, $namespace)[/code]
gdzie:

  • $service_name - nazwa pod jaką będzie widoczna nasza usługa
  • $namespace - przestrzeń nazw dla dokumentu XML, podamy tutaj na razie 127.0.0.1


Użyjemy zatem kodu:
[code]
$namespace = '127.0.0.1';
$server->configureWSDL('mySOAP', $namespace);
[/code]
Następnie określamy używaną przestrzeń nazw za pomocą:
[code]$server->wsdl->schemaTargetNamespace = $namespace;[/code]

Wstępna konfiguracja jest już za nami, mamy więc taki oto kod:
[code]
<?php
/* index.php */
require_once("lib/nusoap.php");
// załączamy bibliotekę nuSOAP

$server = new soap_server(); // tworzymy nowy obiekt serwera SOAP
$namespace = '127.0.0.1'; // definiujemy przestrzeń nazw dla XML

$server->configureWSDL('mySOAP', $namespace);  // konfigurujemy nową usługę
$server->wsdl->schemaTargetNamespace = $namespace; // przypisujemy namespace do struktury tworzonego schematu WSDL
?>
[/code]
Stworzymy sobie teraz opisy metod/funkcji jakie udostępniać będzie nasza usługa.
Na początek stworzymy jedną metodę o nazwie:
[code]getTime()[/code]
przyjmującą jeden parametr określający format pobieranego czasu

Rejestracja metod/funkcji

Tutaj musimy się na chwile zatrzymać.
Każdą udostępnianą metodę/funkcję w nuSOAP musimy najpierw zarejestrować. Rejestracja taka polega na podaniu informacji o danej metodzie takich jak jej nazwa, przyjmowane i zwracane parametry, czy opis. Informacje te są wykorzystywane podczas generowania dokumentu WSDL, a także przez sam serwer podczas wywowyłania ich zdalnie. Metody rejestrujemy za pomocą:
[code]$server->register($method, $input, $output, $namespace, $soap_action, $style, $use, $documentation, $encoding_style);[/code]
gdzie:

  • $method - nazwa naszej metody, lub klasa.nazwa_metody
  • $input - tablica z argumentami jakie przyjmuje metoda, array('NAZWA_ARGUMENTU" => 'TYP_ARGUMENTU')
  • $output - tablica z wartościami jakie zwraca metoda, array('return" => 'TYP_ZWRACANEJ_WARTOŚCI')
  • $namespace - przestrzeń nazw dla XML
  • $soap_action - akcja dla metody lub false 
  • $style - rpc|document, rodzaj generowania odpowiedzi  
  • $use - encode|literal - tryb kodowania znaków  
  • $documentation - opis naszej metody do pliku WSDL  [opcjonalnie]
  • $encoding_style - zewnętrzny styl dla encodowania [opcjonalnie]

Zarejestrujmy teraz naszą metodę o nazwie getTime().
Jak pamiętamy przyjmuje ona jeden parametr typu string, zwraca wartość również typu string - będziemy musieli określić to w metodzie rejestrującej:
[code]
$server->register("getTime"                    
                 ,array('time_format'=>'xsd:string')
                 ,array('return'=>'xsd:string')
                 ,$namespace
                 ,false
                 ,'rpc'
                 ,'encoded'
                 ,'To jest nasza testowa metoda zwracająca czas na serwerze'
                  );
[/code]

Metodę mamy już zarejestrowaną, pora na jej definicję.
Zrobimy to tak jak zwykle, definiując zwykłą funkcję, z małą różnicą na końcu:
[code]
function getTime($time_format)
{
  $result = date($time_format);
  return new soapval('return', 'xsd:string', $result);
}
[/code]
Ta mała różnica to zwracana wartość.
Jak widzimy w funkcji zarejestrowanej dla SOAP nie możemy zwrócić danych tak jak zazwyczaj, czyli poprzez:
[code]return $result;[/code]
Musimy tutaj za każdym razem wykorzystać obiekt klasy soapval, wg następującej składni:
[code]return new soapval(nazwa_zwracanej_wartości, rodzaj_zwracanej_wartości, $wartość);[/code]
Zauważmy, że jako nazwa zwracanej wartości podajemy tutaj return,  co też określiliśmy podcza rejestracji metody w:
[code]array('return'=>'xsd:string')[/code]
Wyjaśnienia wymaga także zapis:
[code]xsd:string[/code]
W schemacie XSD w taki sposób właśnie podawać musimy typ zwracanej wartości.
Podstawowe typy danych to:

  • xsd:string
  • xsd:int
  • xsd:float
  • xsd:double
  • xsd:boolean

Pełną listę znajdziesz tutaj:
http://www.w3schools.com/schema/schema_dtypes_string.asp

Nasz kod w tym momencie wygląda więc tak:
[code]
<?php
/* index.php */
require_once("lib/nusoap.php");
// załączamy bibliotekę nuSOAP

$server = new soap_server(); // tworzymy nowy obiekt serwera SOAP
$namespace = '127.0.0.1'; // definiujemy przestrzeń nazw dla XML

$server->configureWSDL('mySOAP', $namespace);  // konfigurujemy nową usługę
$server->wsdl->schemaTargetNamespace = $namespace; // przypisujemy namespace do struktury tworzonego schematu WSDL

// rejestrujemy metodę
$server->register("getTime"                    
                 ,array('time_format'=>'xsd:string')
                 ,array('return'=>'xsd:string')
                 ,$namespace
                 ,false
                 ,'rpc'
                 ,'encoded'
                 ,'To jest nasza testowa metoda zwracająca czas na serwerze'
                  );
               
// definiujemy metodę                
function getTime($time_format)
{
  $result = date($time_format);
  return new soapval('return', 'xsd:string', $result);
}
?>
[/code]

Teraz musimy jeszcze w jakiś sposób odbierać żądania.
Posłuży do tego poniższy kod:
[code]
$postdata = file_get_contents("php://input");
$postdata = isset($postdata) ? $postdata : '';
[/code]
Na sam koniec startujemy usługę, podając jako parametr ew. odebrane żądanie:
[code]$server->service($postdata);[/code]
Nasz kod finalnie wygląda tak:
[code]
<?php
/* index.php */
require_once("lib/nusoap.php");
// załączamy bibliotekę nuSOAP

$server = new soap_server(); // tworzymy nowy obiekt serwera SOAP
$namespace = '127.0.0.1'; // definiujemy przestrzeń nazw dla XML

$server->configureWSDL('mySOAP', $namespace);  // konfigurujemy nową usługę
$server->wsdl->schemaTargetNamespace = $namespace; // przypisujemy namespace do struktury tworzonego schematu WSDL

// rejestrujemy metodę
$server->register("getTime"                    
                 ,array('time_format'=>'xsd:string')
                 ,array('return'=>'xsd:string')
                 ,$namespace
                 ,false
                 ,'rpc'
                 ,'encoded'
                 ,'To jest nasza testowa metoda zwracająca czas na serwerze'
                  );
               
// definiujemy metodę                
function getTime($time_format)
{
  $result = date($time_format);
  return new soapval('return', 'xsd:string', $result);
}

// odbieramy żądanie
$postdata = file_get_contents("php://input");
$postdata = isset($postdata) ? $postdata : '';

// startujemy usługę
$server->service($postdata);
?>
[/code]
Wejdżmy teraz w adres naszej usługi:
[code]http://localhost/soap[/code]
Jeśli wszystko wykonaliśmy poprawnie, powinien nam się ukazać opis naszej usługi:



Automatycznie generowany dokument WSDL zobaczymy wpisując adres:
[code]http://localhost/soap?wsdl[/code]
(nuSOAP wymaga podania WSDL małymi literami)



Voila!
Stworzyliśmy swoją własną, prostą usługę sieciową.

Aplikacja kliencka

Teraz czas na przetestowanie naszej usługi. Zobaczymy teraz jak połaczyć się z usługą po stronie klienta.
Stwórzmy plik client.php o następującej treści:
[code]
<?php
/* client.php */
require_once('lib/nusoap.php');
// dołączamy bibliotekę

$wsdl = 'http://localhost/soap/?wsdl'; // URL do wsdl naszego serwera
$client = new nusoap_client($wsdl, 'wsdl'); // tworzymy obiekt klienta
$params = array('time_format' => 'H:i:s'); // definujemy parametry wywoływanej funkcji

$response = $client->call('getTime', $params);
// wywołujemy zdalną funkcję

echo('SERVER TIME: '. $response);
?>
[/code]
W pierwszej kolejności załączamy oczywiście bibliotekę nuSOAP.
Następnie definiujemy URL do naszej usługi (z koncówką ?wsdl) i podajemy go do konstruktora obiektu klienta:
[code]$client = new nusoap_client(url_do_definicji_wsdl, wsdl);[/code]
gdzie w drugim parametrze podajemy wsdl, jeśli łączymy się z definicją WSDL.
W kolejnym kroku definiujemy tablicę z argumentami z jakimi wywołamy zdalną funkcję oraz wywołujemy samą funkcję za pomocą:
[code]$client->call(nazwa_zdalnej_funkcji, parametry);[/code]
Jeśli wszystko poszło po naszej myśli, to powinniśmy połączyć się z naszą usługą sieciową, uruchomić na niej zdalną funkcję i odebrać z serwera wynik jaki zwróciła:


Podsumowanie

Jak widać, nie jest to bardzo skomplikowane.
W kilku krokach stworzyliśmy swój własny serwer SOAP oraz nauczyliśmy się wywoływania zdalnych metod i odbierania od nich danych. Oczywiście są to absolutne podstawy i do bardziej skomplikowanej pracy nie wystarczą, ale jest to już pewna podbudowa, gdy umiemy korzystać z czegoś choćby w wersji podstawowej i wiemy "z czym to się je".

W następnych artykułach opiszę bardziej zaawansowane metody pracy z SOAP wraz z przykładami, a póki co - wiedza zdobyta w tym artykule niech stanowi dla nas podstawę i zachętę do dalszej nauki protokołu SOAP.

Dla ciekawskich: dokumentacja webAPI oferowanego przez Allegro.pl, oczywiście za pomocą SOAP: http://allegro.pl/webapi/documentation.php

26 komentarzy:

  1. Świetny materiał do nauki. Dziękuję bardzo za to.
    Pozdrawiam serdecznie,

    OdpowiedzUsuń
    Odpowiedzi
    1. Cieszę się, że artykuł się przydał.
      Niebawem druga część z opisem bardziej praktycznych zastosowań ;)
      Pozdrawiam.

      Usuń
    2. Bardzo dziękuje nienwiem skąd Tego się uczycie wszystkiego i kto to tworzy hehehe

      Usuń
    3. Php Majster: [Soap] Podstawy Protokołu Soap I Tworzenie Prostej Usługi Sieciowej >>>>> Download Now

      >>>>> Download Full

      Php Majster: [Soap] Podstawy Protokołu Soap I Tworzenie Prostej Usługi Sieciowej >>>>> Download LINK

      >>>>> Download Now

      Php Majster: [Soap] Podstawy Protokołu Soap I Tworzenie Prostej Usługi Sieciowej >>>>> Download Full

      >>>>> Download LINK jk

      Usuń
  2. Super materiał na początek. Właśnie tego potrzebowałem. Dziękuje.

    OdpowiedzUsuń
  3. Dziękuję, fany artykuł. Czy da się w ten sposób zwrócić powielone wartości return?

    data1
    data2
    ...
    data3

    Próbowałem z tablicą, ale nie chce mi wygenerować poprawnego xml. Pozdrawiam

    OdpowiedzUsuń
  4. Trochę przedpotopowa ta biblioteka, nie polecam. Ma jeszcze konstruktory w formie funkcji o nazwie klasy. A swoją drogą, to konstruktor klasy nusoap_client nie chce od nas stringa "wsdl" w drugim parametrze, jeśli używamy WSDL. To jest parametr typu boolean. True dla WSDL, false jeśli to nie WSDL.

    OdpowiedzUsuń
  5. Dopisuję się do powyższego, u mnie wszystko działa . Supcio!

    OdpowiedzUsuń
  6. Bardzo przydatny artykuł, dzięki!

    OdpowiedzUsuń
  7. Muszę przyznać, że jak czytam Twoje wpisy to widzę że masz bardzo dobre pojęcie o pisaniu programów w PHP. Ja niestety zatrzymałem się daleko w tyle i stwierdzam, ze stworzenie oprogramowania wolę zostawić profesjonalistom jak https://craftware.pl a ja skupiam się na jego promocji. Fajnie, że są ludzie którzy to wszystko ogarniają gdyż wiem, że kodowanie to nie jest nic łatwego i trzeba poświęcić bardzo dużo czasu na naukę.

    OdpowiedzUsuń
  8. Php Majster: [Soap] Podstawy Protokołu Soap I Tworzenie Prostej Usługi Sieciowej >>>>> Download Now

    >>>>> Download Full

    Php Majster: [Soap] Podstawy Protokołu Soap I Tworzenie Prostej Usługi Sieciowej >>>>> Download LINK

    >>>>> Download Now

    Php Majster: [Soap] Podstawy Protokołu Soap I Tworzenie Prostej Usługi Sieciowej >>>>> Download Full

    >>>>> Download LINK

    OdpowiedzUsuń

Masz sugestię? Znalazłeś błąd? Napisz komentarz! :)

webmaester.pl - profesjonalne projektowanie WWW i webaplikacji
webmaester.pl - profesjonalne projektowanie WWW i webaplikacji