Python, SOAP, REST i Rails
Posted by Jarosław Zabiełło Fri, 23 Mar 2007 00:50:00 GMT
Ostatnie problemy z podłączeniem się z poziomu Pythona do do web serwisów napisanych w C#/.NET zmusiły mnie do głębszego spojrzenia na kwestię promowanego przez Microsoft (i kiedyś Macromedię1) tworzenia aplikacji za pomocą web serwisów i związanego z nim protokołu SOAP. Może wpierw krótko naświetlę problem jaki napotkałem w Pythonie.
Problem dotyczył konieczności połączenia się za pomocą Pythona z z dotnetowym web serwisem napisanym w C#. Wybrana biblioteka ZSI 2.0rc3 bezskutecznie próbowała zestawić połączenie:
from ZSI.ServiceProxy import ServiceProxy
wsdl = 'http://localhost/web/MyAction.asmx?wsdl'
print ServiceProxy(wsdl, tracefile=sys.stdout) Można było zobaczyć dziwaczny błąd:
"C:\opt\Python25\lib\site-packages\zsi-2.0_rc3-py2.5.egg\ZSI\wstools\WSDLTools.py",
line 1116, in getAddressBinding
WSDLError: No address binding found in port. Nawet gdybym chciał, to debugowanie źródeł biblioteki ZSI byłoby raczej mało poręczne (ZSI zainstalowała się w postaci jednego, binarnego pliku egg). Domyśliłem się że problemem jest chyba jakaś różnica w microsoftowej implementacji SOAP bo ten sam kod bez problemu łączył się z web serwisami Googli (których raczej nie ma co podejrzewać że korzystają z .NET) Co ciekawe, mogłem bez problemu połączyć się z tymi web serwisami .NET ale za pomocą… Rubiego. Być może to, że SOAP jest włączony do standardowej biblioteki Rubiego spowodował że po prostu porządnie ktoś tą bibliotekę napisał i przetestował.
W przypadku Pythona istnieje wiele różnych, niezależnych bibliotek SOAP, żadna nie została włączona do biblioteki standardowej. Może w końcu ktoś pomyśli, że to wstyd aby biblioteki standardowe Python obsługiwały tylko XML-RPC. Bez względu krytykę i wady SOAP jest propagowany przez kręgi Javy i .NET więc trochę głupio to tak ignorować. Nawet PHP5 doczekał się dobrej biblioteki SOAP włączonej do standardowych modułów. Muszę wypróbować jeszcze inne biblioteki, może któraś “ruszy”. Próbowałem zainstalować SOAPpy, ale wymagała biblioteki fpconst, ta zaś nie ma przygotowanego pakietu egg dla Pythona 2.5. W końcu do obszedłem instalując pakiet za pomocą klasycznej mantry: python setup.py install. Jak SOAPpy nie zadziała, to na liście do sprawdzenia mam jeszcze soaplib. SOAPpy tu zadziałał ale wysypuje się w innym miejscu…
Próbując rozwiązać problem dotarłem dobardzo ciekawych tekstów polemiki SOAP vs REST. Chodzi mi o artykuł The S stands for Simple oraz 3-częściowy (kolejne mają być napisane) The REST Dialogues. Ten drugi to ciekawy dialog z fikcyjnym pracownikiem eBay (preferującym klasyczne podejście z SOAP i udostępnianiem dziesiątek funkcji) ze zwolennikiem REST’a.
Lektura tych tekstów uświadomiła mi kilka rzeczy. Np. dlaczego jedne web serwisy Googli działają a Microsoftu – nie. Wszystko wskazuj na to, że SOAP jest kiepskim protokołem. Jest niedopracowany i niejednoznaczny co daje innym za duże pole do wprowadzania autorskich modyfikacji. kto jak kto, al e firma M$ bardzo skwapliwie z takich rzeczy korzysta. Microsoft się chyba lubuje we wprowadzaniu zamieszania. Ich Internet Explorer nie tylko do dziś ma zamiaru liczy się ze standardami W3C ale także nie jest zgodny ze samym sobą (tj. wcześniejszymi swymi wersjami). Założę się że coś spieprzyli z SOAP. Jak ma się szczęście to działa, jak nie, to zmuszają cię abyś korzystał z Windozy i ich rozwiązań. Taka ich durna strategia że M$ ma najwyraźniej wszystkie standardy gdzieś i chce aby jego “pomysły” były standardem i prawem dla wszystkich.
Druga rzecz, to sama kwestia filozofii REST vs klasyczne web serwisy. Np. deweloperzy Railsów, mimo że wspierają jeszcze SOAP oraz i XML-RPC planują wyrzucić obie te biblioteki poza nawias głównego kodu swojego frameworka. Chcą się zamiast tego skupić na REST. W kolejnych wersjach Railsów (2.0?) SOAP i XML-RPC będą co prawda dostępne ale już tylko jako dodatkowe pluginy.
REST to nie ładniejsze adresy URL i prostsze operacje czytania i zmiany zasobów serwera,. To także trochę inna filozofia pracy związana z podejściem deklaratywnym a nie imperatywnym. Oparta nie tyle na zdarzeniach, co na stanach zasobów identyfikowanych jednoznacznie przez adres URL i przypisaną mu akcję. (W najprotszej postaci GET służy do odczytu zasobu, a POST do zmiany jego stanu).
Sprawa wygląd ciekawie i jestem zachęcony aby ją zbadać i opisać poźniej dokładniej i na przykładach. Na razie odsyłam do w/w artykułów które wszystko opisują bardziej szczegółowo. Miłośników Railsów odsyłam też do książki Rails Cookbook która ma cały rozdział poświęcony zastosowaniu w REST w Ruby on Rails.
1 Jakiś czas temu na jednej z konferencji w Warszawie firma Macromedia wychwalała pod niebiosa używanie web serwisów we Flashu. Aktualnie Macromedię wchłonęła firma Adobe.


Kanały IRC![[Dilber w Onecie]](/images/larry.png)


“mimo że wspierają jeszcze SOAP oraz i XML-RPC planują wyrzucić obie te biblioteki poza nawias” – może warto zauważyć, że SOAP i XML-RPC to nie biblioteki, a protokoły…
“może warto zauważyć, że SOAP i XML-RPC to nie biblioteki, a protokoły…”
Czepiasz się. Ja tu widzę zwykły skrót myślowy…
A co do REST on Rails, to znalazłem fajną książkę w pdfie, która fajnie opisuje jak się szybko przerzucić. Jeżeli ktoś nie ma dostępu do publikacji papierowych, to będzie w sam raz :)
Przecież nie można wyrzucić protokołów z core code. :) Wyrzuca się tylko biblioteki. Oczywiście że to był skrót. BTW, SOAPpy zadziałał (choć musiałem poprawić 3 trywialne błędy w źródle blokujące jego działanie dla Pythona 2.5)
eggi to zwykłe archiwa zip
To na czym w końcu lepiej się opierać na REST czy SOAP??
Które rozwiazanie jest ciekawsze/lepsze ?? ==== Proszę o konkrety :)
Szczerze: xml-rpc :) trochę zapomniany, lekki (o ile można użyć takiego określenia do xml’a), oferuje podobne możliwości jak soap, a przy tym prosty jak drut (pełna specyfikacja to kilka stron..). Ewentualnie JSON-RPC (zaleta: 0% xml’a, reszta jak w xml-rpc:)
Skoro znalaxł pan buga w soappy to proponuje zglosic jakiegos patcha. A tak w temacie to mi np ZSI nie dziala z serwisem http://www.xmethods.net/sd/2001/TemperatureService.wsdl przy wywolaniu mentody getTempt pluje wyjatkiem natomiast soappy dziala bez zarzutu, a to podobno zsi jest bardziej rozwijany i ma zastapic soappy. Do tego ma tak trywialne bugi jak przekazanie dwoch argumentow do funkcji str. Zenada
A możesz zaprezentować tego WSDL’a – może coś tam się niezbyt ładnie wygenerowało – np. próbujesz na zewnątrz wyrzucić dane, których typy nie zostały rozbite na części (typy) pierwsze zrozumiałe przez namespace’y W3C (standardowo, jeśli wygenerowałeś WSDL’a z kodu, może tak być), może też chodzić o jakieś inne inszości.
Generalnie problem z WS’ami w .NET’cie jest taki, że sporo ludzi najpierw pisze kod, później generuje WSDL’a, i dopiero integrując to z czymś zewnętrznym dziwi się, że nie działa.. A przecież (IMHO) WSDL powinien być napisany przed kodem, i kod powinien być pod niego podrasowany. Z tego co pamiętam, np. w gSOAP’ie (w C++) miałem webserwis który definiował sobie enumerację w której nie tolerował znaczka ’_’ (albo ‘‘), natomiast dokładnie na odwrót było w .NET’cie ;))
Stic, oto wersja zsi(nie dzialajaca): from ZSI.ServiceProxy import ServiceProxy import sys
wsdlFile = ‘http://www.xmethods.net/sd/2001/TemperatureService.wsdl’ proxy = ServiceProxy(wsdlFile, tracefile=sys.stdout) print print proxy.getTemp(Message = ‘80218’)
a to wersja soappy(dzialajaca): from SOAPpy import WSDL
wsdlFile = ‘http://www.xmethods.net/sd/2001/TemperatureService.wsdl’ server = WSDL.Proxy(wsdlFile) print server.getTemp(‘80218’)