101 implementacji HTTP

Poprzednia wersja libpurple cierpiała na brak dobrej implementacji połączeń HTTP. Zwyczajny użytkownik nie zauważy tego, ponieważ wtyczki starają się zakryć problemy z tego wynikające. Jednak gdy każdy komponent korzystający z takich zapytań musi radzić sobie z każdym z tych problemów z osobna, co nie może się skończyć dobrze.

Prawie rok temu zdecydowałem pójść inną drogą niż dotychczasowi autorzy wtyczek – zamiast tworzyć kolejną, wewnętrzną implementację, zaprojektowałem i wykonałem nowe, elastyczne API HTTP. Teraz zszedłem jeszcze głębiej, zastępując wszystkie dotychczasowe wersje moim nowym dziełem.

Zadanie to składało się z kilku etapów. Najpierw zamieniłem wszystkie użycia purple_util_fetch_url nowym, purple_http_get. To był całkiem łatwy krok, ponieważ obie funkcje robiły mniej więcej to samo: na podstawie URL pobierały i zwracały jego zawartość. Następnie przyszła kolej na coś trudniejszego: purple_util_fetch_url_request wymagał ręcznego budowania i parsowania nagłówków HTTP. Ponadto, przerzucał część obsługi proxy na kod zlecający żądanie, w dodatku w dziwny sposób – należało w nagłówku HTTP przekazać pełny URL, jeżeli korzystano z proxy, lub krótki (bez nazwy hosta) w przeciwnym przypadku.

Pozbycie się funkcji purple_util_fetch_url* podniosło jakość kodu, ale najtrudniejsze zadanie wciąż czekało na wykonanie. Część protokołów posiadało własne implementacje HTTP – proszę sobie tylko wyobrazić ilość kopiuj-wklej. Chciałbym przedstawić kilka przykładów usuniętego przeze mnie kodu:

  • oscar (ICQ, AIM) zawierał własny kod HTTP tylko po to, aby wykonać proste zapytanie GET; implementacja była tak ochydna, że sam autor nazwał funkcje straight_to_hell, damn_you i struct pieceofcrap; na szczęście, ten kod nie był używany od dłuższego czasu;
  • mxit: tutaj można było to zrobić z wykorzystaniem starego API, nie mam pojęcia, dlaczego autor tego nie zrobił;
  • msn: w tym przypadku można mówić o pewnym usprawiedliwieniu – stare API nie posiadało wsparcia dla połączeń Keep-Alive, więc autor zrobił je po swojemu, by zyskać trochę na wydajności; niestety, zrobił to dwa razy (dla serwerów pośredniczących oraz obsługi SOAP);
  • xmpp również posiadało dwie implementacje, jednak nie w tak oczywisty sposób nadmiarowe: obsługa BOSH była skomplikowana i pełna notatek TODO; wykorzystywała zwykłe połączenia Keep-Alive, ale w bardzo dziwny i zaciemniony sposób; przepisanie drugiej (transferu plików out-of-band) było dla odmiany przyjemnością (szczególnie, że już robiłem coś podobnego dla Gadu-Gadu);
  • yahoo jest rekordzistą w tej kategorii, posiadającym aż cztery różne implementacje HTTP; myślę, że tylko transferu plików w tym protokole nie dało by się zrobić z użyciem starego API.

Wciąż pozostają dwa komponenty z własną obsługą HTTP, ale nie jestem pewien czy w ogóle kiedykolwiek je przepiszę. Pierwszy z nich jest dla protokołu Gadu-Gadu – jest zawarty w bibliotece libgadu, więc wyciągnięcie go stamtąd może być trudne bez naruszania API tej biblioteki. Drugi to komunikator sieci Novel GroupWise – zamknięta usługa, używana przez niektóre większe firmy. Nie ma dla niej publicznych serwerów, na których mógłbym testować. Jest co prawda demo serwera, ale jego instalacja i konfiguracja mnie przerosła (tak naprawdę, to ich instalator chyba zawiera błędy). Nie jestem pewien, czy warto wysilać się dla powyższych dwóch przypadków.

Moim następnym zadaniem będzie udoskonalenie i włączenie wtyczki szyfrowania Off-the-record do głównej gałęzi Pidgina.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *