Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2004.09.26;
Скачать: [xml.tar.bz2];

Вниз

Прокси   Найти похожие ветки 

 
тихий вовочка ©   (2004-07-18 14:57) [0]

Попробовал сделать примитивнейший прокси на 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;


 
Hogo   (2004-07-19 08:13) [1]

Есть компоненты
TIdTunnelMaster
TIdTunnelSlave

и самый простой вариант
IdMappedPortTCP


 
Reindeer Moss Eater ©   (2004-07-19 08:25) [2]

то посылает своего клиента за нужной страничкой или рисунком

И где это в приведенном коде можно увидеь?


 
тихий вовочка ©   (2004-07-19 12:35) [3]

И где это в приведенном коде можно увидеь?

url := "http://" + ARequestInfo.Host + ARequestInfo.Document;
Это получает сервер от браузера

IdHTTP1.Get(url, buf);
Это запускается клиент для скачивания требуемого

AResponseInfo.ContentStream.CopyFrom(buf,buf.Size);
Это сервер передает браузеру то, что скачал клиент


 
Reindeer Moss Eater ©   (2004-07-19 12:39) [4]

Я бы не был так уверен насчет этого:

url := "http://" + ARequestInfo.Host + ARequestInfo.Document;
Это получает сервер от браузера


 
Reindeer Moss Eater ©   (2004-07-19 12:44) [5]

Точнее не был бы так уверен в  правильности формирования url таким способом


 
Reindeer Moss Eater ©   (2004-07-19 12:51) [6]

А если у клиента в запросе необходимые ему куки есть например?
Или параметры для авторизации?


 
nikkie ©   (2004-07-19 15:30) [7]

>[1] Hogo   (19.07.04 08:13)
>Есть компоненты
>TIdTunnelMaster
>TIdTunnelSlave
ну и причем тут они?

>и самый простой вариант
>IdMappedPortTCP
для "прочтейшего прокси" вполне, но автор делает на самом деле http-прокси.


 
Reindeer Moss Eater ©   (2004-07-19 15:32) [8]

И причем неправильно делает.


 
nikkie ©   (2004-07-19 16:06) [9]

не знаю, насколько удачная идея использовать 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;


 
nikkie ©   (2004-07-19 16:10) [10]

блин, отправилось чуть недописанным...
после комментария
// здесь у меня весьма урезанная логика кеширования:
код такой:
     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;
то есть при запросе файла, который есть в локальной директории, прокси отдает его, не обращаясь к сетевому ресурсу.


 
Reindeer Moss Eater ©   (2004-07-19 16:13) [11]

Берем TCPServer.
Организуем цикл readln чтения клиента пока не прочитаем пустую строку.
Request клиента у нас в кармане.
Остается найти в нем host/port.

После чего соединяемся TCPClient"ом c host/port и пишем туда весь заголовок как есть.


 
www_Vlad   (2004-07-19 22:17) [12]

Народ, делаю клиент/серверную софтину, подскажите как сделать, чтобы она могла работать через прокси?


 
VID ©   (2004-07-19 22:49) [13]

Проще всего строить на Indy там свойства Proxy, ProxyPort уже есть в рамках самого компонента (Клиента).


 
тихий вовочка ©   (2004-07-19 23:03) [14]

Берем TCPServer.
Организуем цикл readln чтения клиента пока не прочитаем пустую строку.
Request клиента у нас в кармане.
Остается найти в нем host/port.

Так можно у того же IndyHTTPServer брать RawHTTPString или что-то в этом духе(Делфи нет под рукой)


 
www_Vlad   (2004-07-20 00:50) [15]

Ну насчет tcp-сервера я так понимаю, для него ничего не меняется, сам прокси-сервер мнене нужен, я не его делаю, а вот насчет клиента не совсем понятно, я шлю пакеты на прокси, но как дать понять прокси, куда их затем пересылать?
С инди я посмотрел, спасибо, как их использовать ясно, но мне не совсем идея ясна, объясните плиз. Что нужно послать в порт прокси-серверу, чтобы он перенаправил пакет на другой сервер (если не пользовать компоненты)?



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2004.09.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.037 c
14-1094151899
Knight
2004-09-02 23:04
2004.09.26
Кто знает e-mail адрес SMS шлюза северо-западного Мегафона?


3-1093611893
Kul_Alex
2004-08-27 17:04
2004.09.26
Добавление данных в БД


1-1094908924
][ncognito
2004-09-11 17:22
2004.09.26
Опять вопрос по ТриВью


1-1094816889
Still Swamp
2004-09-10 15:48
2004.09.26
Вызов внешнего редактора HTML


3-1093844052
Ega23
2004-08-30 09:34
2004.09.26
Перехват запросов





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский