logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Delphi] Indy HTTP - błędy przy użyciu Head/Get i uszkodzona treść strony

Dżyszla 02 Lip 2008 18:49 14211 37
Najlepsze odpowiedzi

Dlaczego w Indy `Head`/`Get` dla niektórych stron wywołuje wyjątki, a pobrana treść wygląda na uszkodzoną?

Najprawdopodobniej problem nie leży w samym `Head/Get`, tylko w instalacji/wersji Indy oraz w obsłudze przekierowań serwera; po czystej reinstalacji Indy 10, z usunięciem starych plików `Id*` i kompilacją zgodnie z instrukcją, zniknęły u autora część dziwnych błędów [#5349335] Dla stron zwracających przekierowanie `HEAD` potrafi oddać np. `302`, więc trzeba mieć ustawione `HandleRedirects := True`, bo wtedy Indy obsługuje kody 300–307 [#5347865][#5347981] Jeśli po `Head` robisz `Get`, to pobieraj już URL po przekierowaniu, bo `Get` na pierwotnym adresie może zwracać błąd albo działać dopiero przy drugim wywołaniu [#5347981][#5348139] „Uszkodzona” treść widziana w debuggerze nie musiała być faktycznie uszkodzona — zapis do pliku był poprawny, a podgląd w debuggerze wprowadzał w błąd [#5325059][#5325010]
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA
  • #1 5305983
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Jest sobie taki oto kod:
    var
    	PageContent: String;
    begin
    	try
    		IdHTTP.Head(Page);
    		if (IdHTTP.ResponseCode<>200) or (Copy(IdHTTP.Response.ContentType,1,9)<>'text/html') then Exit;
    		PageContent:=IdHTTP.Get(Page);
    	except
    		Exit;
    	end;
    	if (IdHTTP.ResponseCode<>200) or (Copy(IdHTTP.Response.ContentType,1,9)<>'text/html') then Exit;
    

    i pojawiają się dwa problemy:
    1. Podczas wywoływania Head lub Get np dla strony http://www.google.pl/ pojawia się w Delphi komunikat:
    Cytat:
    ---------------------------
    Debugger Exception Notification
    ---------------------------
    Project PRProject.exe raised exception class EConvertError with message 'Invalid argument to date encode'. Process stopped. Use Step or Run to continue.
    ---------------------------
    OK Help
    ---------------------------

    Który jednak nie przedostaje się dalej i nie ma wpływu na blok try..except

    2. Pobrana treść jest od pewnego (zawsze podobnego) fragmentu zniszczona, i wygląda jak w załączniku (zapis debugera Delphi); poniżej newralgiczny fragment z okolic linii 4, kolumny 2550 wyniku otrzymanego przez przeglądarkę):
    Cytat:
    <span class=gb2><div></div></a'#$12#0'D'#0'ć'#0#0#0#0#0#0#0'T'#$11#$19'ž'#$14#$C'ˇ'#2'`_J'#0'0ŕ'#$B#3',î›'#2


    Czy ja robię coś nie tak?
    Załączniki:
    • response.txt (8.27 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • REKLAMA
  • #2 5324875
    Konto nie istnieje
    Konto nie istnieje  
  • #3 5324897
    krzychoocpp
    VIP Zasłużony dla elektroda
    Posty: 1866
    Pomógł: 387
    Ocena: 58
    Nie jestem specjalistą jeśli chodzi o Indy, ale "http://www.google.pl" nie jest nazwą hosta, więc nic dziwnego że nie działa. Powinno być chyba "www.google.pl".

    Pozdrawiam, Krzysztof.
  • REKLAMA
  • #4 5325010
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Kwestia, że ja nigdzie nie nawiązuję połączenia poprzez connect... Teoretycznie Get() powinien wystarczyć...
    Co do tego pierwszego błędu, to mam wrażenie, ze jest to związane z odpowiedzią serwera z "Content-type", w tkórym zawarte jest dodatkowo kodowanie znaków; albo z samym kodowaniem znaków w UTF-8. W zasadzie to nie zauważyłem, aby wpływało na pracę.

    Co do drugiego - do pliku zawsze zapis szedł poprawnie... Wygląda więc bardziej na bład debuggera.
  • #5 5325031
    Konto nie istnieje
    Konto nie istnieje  
  • #6 5325059
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Ale pobierać adres IP serwera i łączyć się z nim? Nie bardzo wiem, po co... Get() wszak i tak łączy i tak...

    Strumień zapisywany do pliku był poprawny. Podglądany w debugerze - nie :] Choć raczej aplikacja widziała go jednak poprawnie.

    oloam, a co z tym błędem "Invalid argument to date encode"?
  • #7 5325129
    Konto nie istnieje
    Konto nie istnieje  
  • #8 5325196
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Ach, no to nie przypuszczałem. Tylko jest jeden problem...
    procedure Connect(const ATimeout: Integer = IdTimeoutDefault); virtual;
    Nie ma innej procedury,w której by się IP podawało :|

    Dodano po 4 [minuty]:

    A i robiąc tak:
    
    IdHTTP.Host:='64.233.169.147';
    idHTTP.Port:=80;
    IdHTTP.Connect; //S='http://www.google.com/search?client=navclient-auto&ch=6-2011884678&features=Rank&q=info:https://addons.mozilla.org/pl/firefox/addon/1865/'
    S:=IdHTTP.Get(S);
    IdHTTP.Disconnect;
    

    Powstaje błąd:
    ---------------------------
    Debugger Exception Notification
    ---------------------------
    Project PRProject.exe raised exception class EIdOSSLConnectError with message 'Error connecting with SSL.'. Process stopped. Use Step or Run to continue.
    ---------------------------
    OK Help
    ---------------------------
  • #9 5325396
    Konto nie istnieje
    Konto nie istnieje  
  • #10 5325448
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Czy strona wywoływana protokołem HTTP może być w jakikolwiek sposób realizowana przez połączenie szyfrowane? Podejrzewam, że to kolejny błąd w Indy, który parametr potraktował jako protokół nagle...
  • #11 5325488
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #12 5325518
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Ten komponent jest dodany i podpięty pod TIdHTTP. Stosowne biblioteki także znajdują się w katalogu programu.
  • #13 5327568
    Konto nie istnieje
    Konto nie istnieje  
  • #14 5327645
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    To owszem, działa. Nie działało, jesli się wcześniej Connect wywoływało, jak podawałeś wcześniej.

    Zasadniczo to wszystko jakoś się trzyma obenie kupy i działa, pomijając te błedy o "Invalid argument to date encode" widziane wyłacznie przez debugera przy zapytaniach do niektórych stron (m.in. do google o PR), lecz nie mające się zdaje mieć wpływu na nic innego.

    Aha - czasami np przy adrese http://www.google.pl/reader/view/?hl=pl&tab=wy notorycznie TimeOut się pojawia jeszcze...
  • #15 5342590
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    I z tym TimeOutem to jest jeszcze tak, że niekiedy przez Head też sie pojawia - mimo odebrania kodu np 404 lub 403, to pojawia się błąd TimeOut, zamiast błędu serwera. Tak, jakby czekał na nie wiadomo co... Dzieje się np tak na http://www.elka.pw.edu.pl/niematakiejstrony.html
  • #17 5342731
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    a dla head()? JEst ustawione przechwytywanie przekierowań? (HandleRedirect jeśli dobrze pamiętam)

    i którą wersje Indy?

    a może najlepiej podaj wszystkie parametry i kod (*.dfm + *.pas). Bo ja już nie wiem :(
  • REKLAMA
  • #18 5342858
    Konto nie istnieje
    Konto nie istnieje  
  • #19 5342977
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Mam 9, może to dlatego... 10 nie współgra mi z SSL. Pobierając kody nie mogę skompilować - jeśli dobrze pamiętam pisało coś o niezgodności wersji jakiegoś pliku... Jeśli gotowca instalowałem, to taki błąd się pojawiał po odaniu IdSSLIOHandlerSocket do programu.
  • #20 5343015
    Konto nie istnieje
    Konto nie istnieje  
  • #21 5343113
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    W zasadzie najnowsza wersja to tylko przez automatyczny instalator. Instaluję jeszcze raz... Pisze, że tego SSL nie ma starego, więc dodaję komponent IdSSLIOHandlerSocketOpenSSL, łączę z IdHTTP, kompiluję i...
    [Fatal Error] PRUnit.pas(12): Unit IdIOHandlerStack was compiled with a different version of IdGlobal.TIdBytes
  • #22 5343149
    Konto nie istnieje
    Konto nie istnieje  
  • #23 5343246
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    No nic, jakoś nakasowałem się wszystko już co było mozliwe i nazywało się indy lub Id* i jakoś wreszsie udało się zainstalowac... Teraz timeoutów nie ma tylko 404 bądź 403 (np dla http://www.elka.pw.edu.pl/UserFiles/File/uplo...enty/Rada_Wydzialu/Komisje/EIK_przedm_ob.doc), lecz wywoływane po strasznie długim czasie (de facto - przekroczeniu timeouta). Co gorsze IdAntyfreeze nie spełnia w tym czasie swojej roli i wątek zostaje zawieszony.

    Dodano po 30 [minuty]:

    Jeszcze jeden problem - http://www.wcsrn.com.pl/ - nie pobiera zawartości tej strony, jeśli podpięty jest SSL pod IoHandler. Zaczyna mnie wkur..zać ten Indy... :[ Co gorsze po zapytaniu o treść tej strony już żadnej więcej nie pobierze.

    I kolejny problem - http://www.uj.edu.pl/index.html nie pobiera tej strony także Wywala
    ---------------------------
    Debugger Exception Notification
    ---------------------------
    Project PRProject.exe raised exception class EIdHTTPProtocolException with message '<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">'. Process stopped. Use Step or Run to continue.
    ---------------------------
    OK   Help   
    ---------------------------
    
    Na prawdę szlag mnie trafi z tym Indy :evil:

    I dzieje się to zawsze, gdy wcześniej wywołam Head(). Jeśli wywołuję samo Get() (w osobnej procedurze) to jest ok (pierwsze błąd, drugie ok).
    
    procedure TMainForm.Memo1DblClick(Sender: TObject);
    begin
    try
    	IdHTTP.Head('http://www.uj.edu.pl/'); //timeout się pojawia
    except end;
    	Memo1.Text:=IdHTTP.Get('http://www.uj.edu.pl/index.html'); //i tak nie pobiera zgłaszając bład, jakby wszystko poza nagłówkiem zaczęło płynąć.
    end;
    
    procedure TMainForm.Memo1KeyPress(Sender: TObject; var Key: Char);
    begin
    	Memo1.Text:=IdHTTP.Get('http://www.uj.edu.pl/index.html');
    end;
    
  • #24 5347865
    Konto nie istnieje
    Konto nie istnieje  
  • #25 5347949
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    HandleRedirects jest ustawione na True, a Get'a nie będę używał za każdym razem, bo nie potrzebuję pobierać wszystkiego jak leci, a jedynie pliki formatu txt/html (czy tam html/txt). Dlatego właśnie używam Head zgodnie z zastosowaniem sugerowanym w opisie.
    Zaraz jeszcze kolejne testy będę przeprowadzał - zleceniodawca wciąż twierdzi, że na jednej stronie się wiesza :/
  • #26 5347981
    Konto nie istnieje
    Konto nie istnieje  
  • #27 5348139
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    Tak, działa (lecz i tak timeout dopiero przerywa połączenie). Lecz wywołując taką sekwencję zapytań, GET nie działa:
    
       IdHTTP.Head('http://www.uj.edu.pl/');
    except end;
       Memo1.Text:=IdHTTP.Get('http://www.uj.edu.pl/index.html');
    Chodziło o stronę http://www.uj.edu.pl/ dla HEAD, GET operuje już na przekierowanej.
    Telnetem wywołując zapytania wygląda tak, że nagłówek jest zwracany, lecz serwer nie zrywa połączenia.
  • #28 5348716
    Konto nie istnieje
    Konto nie istnieje  
  • #29 5349082
    Dżyszla
    Poziom 42  
    Posty: 7077
    Pomógł: 1095
    Ocena: 226
    W dalszym ciągu niestety niczego to nie zmienia. Gdy Get wywoływane jest po Head dla tej strony - zwraca błąd :( Wygląda to tak, jakby zamiast wykonać pełny GET, serwer zwracał już wyłącznie treść, bez nagłówka. Dopiero drugi raz wywołanie Get przynosi efekt.

    Już kombinowałem, co może być nie tak, ale stwierdzić można chyba tylko jedno - Indy jest badziewiem!
    Poskracałem Timeouty, bo to bez sensu czekać kilka sekund aż łaskawie metoda raczy zwrócić 404 czy 403... Zapętlam Get w przyapadku błedów... I tak jakoś na razie radzę sobie. Ale głęboko się zastanawiam, czy nie napisać od podstaw klienta HTTP... Albo zaprzędz do pracy IE.

    Generalnie to można uprościć, że program tworzy mapę strony na podstawie jej zawartości. Dlatego zapytania dość lawinowo się kierują, a aby nie pobierać rysunków czy innych pierdół, właśnie jest używane Head.

    A żeby było śmieszniej, to dla pewności działania SSL jest podpisane dynamicznie tylko wtedy, gdy w nazwie adresu jest określony protokół https - inaczej też się potrafi sypnąć na niektórych serwerach. Paranoja z tym Indy.

    Czyli raczej nie znajdę rozwiązania problemu, jak Head ma natychmiast zwracać wykryty kod błędu zamiast czekać czort wie na co? BTW - przy tym czekaniu to Antyfreez nie działa (zastanawiam się, czy nie przenieść wszystkiego do osobnego wątku), ani nawet zdaje się Disconnect nie przynosi efektu. A już pomijam, że jak się mu coś poprzestawia (przenośnia), to tylko restart programu pomaga.
  • #30 5349135
    Konto nie istnieje
    Konto nie istnieje  

Podsumowanie tematu

✨ Dyskusja dotyczy problemów z używaniem komponentu Indy TIdHTTP w Delphi do wykonywania zapytań HTTP metodami HEAD i GET. Główne problemy to błędy pojawiające się przy wywołaniu Head/Get, m.in. komunikat "Invalid argument to date encode" widoczny w debugerze, oraz uszkodzona lub niepełna zawartość pobieranych stron. Wskazano, że problem może wynikać z błędów w tłumaczeniu DNS przez Indy, co można obejść podając adres IP zamiast nazwy hosta. Dyskutowano także o konieczności stosowania komponentu SSL (TIdSSLIOHandlerSocketOpenSSL) do obsługi połączeń HTTPS, a także o problemach z instalacją i kompatybilnością wersji Indy 9 i Indy 10, zwłaszcza w kontekście SSL. Poruszono kwestie timeoutów i obsługi przekierowań HTTP (kodów 3xx) oraz sugestię, by w przypadku błędów po HEAD wywoływać GET. Zauważono, że niektóre serwery długo odpowiadają na HEAD, co może powodować timeouty i zawieszanie wątków, a także problemy z dekompresją odpowiedzi przy użyciu komponentu IdCompressorZLib, skutkujące błędami ZLib. Wskazano na potrzebę poprawnej instalacji Indy, usunięcia starych wersji i właściwej konfiguracji komponentów, aby uniknąć błędów kompilacji i działania. Ogólnie Indy jest oceniany jako funkcjonalny, ale z licznymi problemami i ograniczeniami, zwłaszcza przy niestandardowych zachowaniach serwerów i obsłudze SSL.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA