![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Прокси
тихий вовочка © (2004-07-18 14:57:00)Попробовал сделать примитивнейший прокси на Indy. Но у меня ничего не получается. Не могу нормально состыковать IndyHTTPServer и IndyHTTPClient. То есть логика проста - браузер передает запрос моему серверу, то посылает своего клиента за нужной страничкой или рисунком(рисунки у меня только принудительно грузяться вообще), а потом переправляет это все браузеру. Без кеширования, анализа и прочего. Просто взял - отдал. Что я делаю нерпавильно?
procedure TForm1.IdHTTPServer1CommandGet(AThread: TIdPeerThread;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
url : string;
buf : TMemoryStream;
begin
buf := TMemoryStream.Create;
buf.Clear;
buf.Position := 0;
url := 'http://' + ARequestInfo.Host + ARequestInfo.Document;
if ARequestInfo.Command = 'GET' then
begin
ListBox1.Items.Add('GET');
IdHTTP1.Get(url, buf);
end
else
if ARequestInfo.Command = 'POST' then
begin
ListBox1.Items.Add('POST');
end
else
if ARequestInfo.Command = 'PUT' then
begin
ListBox1.Items.Add('PUT');
end
else
if ARequestInfo.Command = 'HEAD' then
begin
ListBox1.Items.Add('HEAD');
end;
if AResponseInfo.ContentStream = nil then
begin
ListBox1.Items.Add('nil');
end;
AResponseInfo.ContentStream := TMemoryStream.Create;
buf.Position := 0;
AResponseInfo.ContentStream.CopyFrom(buf,buf.Size);
buf.Free;
AResponseInfo.WriteContent;
AResponseInfo.CloseConnection := true;
AResponseInfo.ContentStream.Free;
end;
www_Vlad (2004-07-20 00:50:00) [1]Ну насчет tcp-сервера я так понимаю, для него ничего не меняется, сам прокси-сервер мнене нужен, я не его делаю, а вот насчет клиента не совсем понятно, я шлю пакеты на прокси, но как дать понять прокси, куда их затем пересылать?
С инди я посмотрел, спасибо, как их использовать ясно, но мне не совсем идея ясна, объясните плиз. Что нужно послать в порт прокси-серверу, чтобы он перенаправил пакет на другой сервер (если не пользовать компоненты)?
тихий вовочка (2004-07-19 23:03:00) [2]Берем TCPServer.
Организуем цикл readln чтения клиента пока не прочитаем пустую строку.
Request клиента у нас в кармане.
Остается найти в нем host/port.
Так можно у того же IndyHTTPServer брать RawHTTPString или что-то в этом духе(Делфи нет под рукой)
VID (2004-07-19 22:49:00) [3]Проще всего строить на Indy там свойства Proxy, ProxyPort уже есть в рамках самого компонента (Клиента).
www_Vlad (2004-07-19 22:17:00) [4]Народ, делаю клиент/серверную софтину, подскажите как сделать, чтобы она могла работать через прокси?
Reindeer Moss Eater (2004-07-19 16:13:00) [5]Берем TCPServer.
Организуем цикл readln чтения клиента пока не прочитаем пустую строку.
Request клиента у нас в кармане.
Остается найти в нем host/port.
После чего соединяемся TCPClient'ом c host/port и пишем туда весь заголовок как есть.
nikkie (2004-07-19 16:10:00) [6]блин, отправилось чуть недописанным...
после комментария
// здесь у меня весьма урезанная логика кеширования:
код такой:
Dir := 'какой-то путь';
FileName := Dir + FileName;
if FileExists(FileName) then begin
AThread.Connection.WriteLn('HTTP/1.1 200 OK');
AThread.Connection.WriteLn('Connection: close');
AThread.Connection.WriteLn;
AThread.Connection.WriteFile(FileName);
abort;
end;
то есть при запросе файла, который есть в локальной директории, прокси отдает его, не обращаясь к сетевому ресурсу.
nikkie (2004-07-19 16:06:00) [7]не знаю, насколько удачная идея использовать idHTTPServer для прокси.
мне так помниться, что он разбирает request в поля RequestInfo, потом придется самому собирать их обратно.
я делал прокси на основе TIdMappedPortTCP.
THTTPProxy = class (TIdMappedPortTCP)
protected
procedure DoConnect(AThread: TIdPeerThread); override;
end;
function ChrPos(S: String; Ch: Char; Start: Integer = 1): Integer;
var
Len: Integer;
begin
Result := 0;
Len := Length(S);
while Start <= Len do begin
if S[Start] = Ch then begin
Result := Start;
break;
end;
Inc(Start);
end;
end;
function ChrPosR(S: String; Ch: Char; Start: Integer = -1): Integer;
begin
Result := 0;
if Start = -1 then Start := Length(S);
while Start >= 1 do begin
if S[Start] = Ch then begin
Result := Start;
break;
end;
Dec(Start);
end;
end;
procedure THTTPProxy.DoConnect(AThread: TIdPeerThread);
var
Request: TStringList;
Command, Protocol, Url, Host, Port, Path, Dir, FileName: String;
idx1, idx2, idx: integer;
begin
Request := TStringList.Create;
try
repeat
Command := AThread.Connection.ReadLn('');
Request.Add(Command);
until Command = '';
Command := Request[0];
idx1 := ChrPos(PChar(Command), ' ');
idx2 := ChrPosR(PChar(Command), ' ');
if idx1 = idx2 then begin // 0 or 1 space
AThread.Connection.WriteLn('HTTP/1.1 400 Bad Request');
abort;
end;
Protocol := Copy(Command, idx2 + 1, Length(Command) - idx2);
Url := Copy(Command, idx1 + 1, idx2 - idx1 - 1);
Command := Copy(Command, 1, idx1 - 1);
Port := '';
if AnsiStartsText('http:', Url) then begin
Delete(Url, 1, Length('http:'));
Port := '80';
end;
if AnsiStartsText('https:', Url) then begin
Delete(Url, 1, Length('https:'));
Port := '443';
end;
if AnsiStartsText('//', Url) then begin
Delete(Url, 1, Length('//'));
end;
idx := ChrPos(Url, '/');
if idx > 0 then begin
Host := Copy(Url, 1, idx - 1);
Path := Copy(Url, idx, Length(Url) - idx + 1);
end else begin
Host := Url;
Path := '/';
end;
idx := ChrPos(Host, ':');
if idx > 0 then begin
Port := Copy(Url, idx + 1, Length(Url) - idx);
Host := Copy(Host, 1, idx - 1);
end;
if Length(Path) = 0 then Path := '/';
idx := ChrPosR(Path, '/');
Assert(idx > 0);
FileName := Copy(Path, idx + 1, Length(Path) - idx);
if Length(FileName) > 0 then begin
// здесь у меня весьма урезанная логика кеширования:
end;
Request[0] := Command + ' ' + Path + ' ' + Protocol;
MappedHost := Host;
MappedPort := StrToIntDef(Port, 80);
inherited;
if not AnsiSameText(Command, 'CONNECT') then begin
TIdMappedPortTCPData(AThread.Data).OutboundClient.Write(Request.Text);
end;
if AThread.Connection.CurrentReadBufferSize > 0 then begin
TIdMappedPortTCPData(AThread.Data).OutboundClient.Write(
AThread.Connection.ExtractXBytesFromBuffer(AThread.Connection.CurrentReadBufferSize));
end;
finally
Request.Free;
end;
end;
Reindeer Moss Eater (2004-07-19 15:32:00) [8]И причем неправильно делает.
nikkie (2004-07-19 15:30:00) [9]>[1] Hogo (19.07.04 08:13)
>Есть компоненты
>TIdTunnelMaster
>TIdTunnelSlave
ну и причем тут они?
>и самый простой вариант
>IdMappedPortTCP
для "прочтейшего прокси" вполне, но автор делает на самом деле http-прокси.
Reindeer Moss Eater (2004-07-19 12:51:00) [10]А если у клиента в запросе необходимые ему куки есть например?
Или параметры для авторизации?
Reindeer Moss Eater (2004-07-19 12:44:00) [11]Точнее не был бы так уверен в правильности формирования url таким способом
Reindeer Moss Eater (2004-07-19 12:39:00) [12]Я бы не был так уверен насчет этого:
url := 'http://' + ARequestInfo.Host + ARequestInfo.Document;
Это получает сервер от браузера
тихий вовочка (2004-07-19 12:35:00) [13]И где это в приведенном коде можно увидеь?
url := 'http://' + ARequestInfo.Host + ARequestInfo.Document;
Это получает сервер от браузера
IdHTTP1.Get(url, buf);
Это запускается клиент для скачивания требуемого
AResponseInfo.ContentStream.CopyFrom(buf,buf.Size);
Это сервер передает браузеру то, что скачал клиент
Reindeer Moss Eater (2004-07-19 08:25:00) [14]то посылает своего клиента за нужной страничкой или рисунком
И где это в приведенном коде можно увидеь?
Hogo (2004-07-19 08:13:00) [15]Есть компоненты
TIdTunnelMaster
TIdTunnelSlave
и самый простой вариант
IdMappedPortTCP