Auch wenn's etwas länger gedauert hat: Hier kommt der versprochene Beispielcode, um aus TIdHTTPServer einen voll steuerbaren Proxy zu basteln:
Delphi-Quellcode:
procedure TForm1.IdHTTPServer1CommandGet(AContext: TIdContext; ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
URL:
String;
HTTP: TIdHTTP;
begin
HTTP:=TIdHTTP.Create;
try
HTTP.Request.Assign(ARequestInfo);
//Dinge, die bei Assign nicht mit übertragen werden:
HTTP.Request.Authentication:=ARequestInfo.Authentication;
HTTP.Request.BasicAuthentication:=ARequestInfo.BasicAuthentication;
HTTP.Request.From:=ARequestInfo.From;
HTTP.Request.Host:=ARequestInfo.Host;
HTTP.Request.Range:=ARequestInfo.Range;
//Kekse übergeben:
//Die Übertragung erfolgt mit einen Trick, da der "offizielle" Weg über den Cookie-Manager
//fehlerhaft ist (IdCookie.ExtractNextCookie() parst Client-Cookies falsch!!!).
HTTP.Request.CustomHeaders.Add('
Cookie: '+ARequestInfo.RawHeaders.Values['
Cookie']);
//Stream für Daten erstellen:
AResponseInfo.ContentStream:=TMemoryStream.Create;
//Anfrage zusammenstellen:
{$IFDEF 10_5_7}
URL:=ARequestInfo.URI;
{$ELSE}
URL:=ARequestInfo.RawHTTPCommand;
Fetch(
URL,'
');
//Kommando entfernen (z.B. 'GET'
URL:=Fetch(
URL,'
');
//komplette Anfrage ermitteln und HTTP-Typ entfernen (z.B. 'HTTP/1.0')
URL:=Fetch(
URL,'
?');
//Anfrage-Parameter entfernen
{$ENDIF}
if ARequestInfo.QueryParams<>'
'
then URL:=
URL+'
?'+ARequestInfo.QueryParams;
//Anfrage an Server:
try
HTTP.Get(
URL,AResponseInfo.ContentStream,[301,302]);
except
end;
//Antwort übergeben:
AResponseInfo.RawHeaders.Assign(HTTP.Response.RawHeaders);
//Reaktion auf bestimmte Antworten:
case HTTP.Response.ResponseCode
of
301, 302: AResponseInfo.Redirect(HTTP.Response.RawHeaders.Values['
Location']);
end;
finally
HTTP.Free;
end;
end;
Dabei handelt es sich nur um einen prinzipiellen Entwurf, der viele Speziallfälle noch nicht berücksichtigt! Desweiteren beherrschen weder das Beispiel noch die
Indy-Komponenten das Streaming von Daten. Diese werden in der aktuellen
Indy Version 10 in einem Stück übertragen. Das Anschauen eines YouTube-Videos endet also mit großer Wahrscheinlichkeit im Task-Manager...
Getestet habe ich den Proxy in einem kleinen Programm, das den Datenverkehr zwischen Client (TWebBrowser) und Server protokolliert:
In der oben beschriebenen Methode kann jetzt nach Lust und Laune an den einzelnen Werten herumgeschraubt werden.
Zum Beispiel wäre die Zwischenschaltung eines weiteren Proxys möglich:
Delphi-Quellcode:
//nächsten Proxy einstellen:
HTTP.UseProxy:=true;
HTTP.ProxyParams.ProxyServer:=naechster_Proxy;
HTTP.ProxyParams.ProxyPort:=80;
HTTP.ProxyParams.ProxyUsername:=Username;
HTTP.ProxyParams.ProxyPassword:=Password;
Möchte ich Google Maps auf hebräisch, muß ich nur die Sprache ändern:
Delphi-Quellcode:
HTTP.Request.AcceptLanguage:='he';
//...
Soll eine Anfrage blockiert werden, reicht folgender Code:
Delphi-Quellcode:
if SameStr(ARequestInfo.URI,'unbeliebt') then
begin
AResponseInfo.ResponseNo:=204; //'HTTP/1.1 204 No Content'
Exit;
end;
Ist man der Meinung, daß es niemanden etwas angeht, mit welchem Browser man unterwegs ist, kann das so verhindert werden:
Delphi-Quellcode:
HTTP.Request.UserAgent:='Mozilla/3.0 (compatible)';
//...
Baut man das Ganze noch etwas aus, ließe sich mit einer Black-List gezielt Werbung unterdrücken. Und da gibt es sicherlich noch etliche weitere Dinge, die man mit einem solchen Proxy anstellen könnte...
Quelltext für eine einfache Demo mit TEmbeddedWB und TIdHTTPServer: