Кеширующий прокси на основе IndyHttpProxyServer

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by Rastamanka, 3 Mar 2012.

  1. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Добрый день. Подскажите как можно сделать кеширующий http прокси на основе IndyHttpProxyServer. Чтобы кешировались к примеру тока картинки,флешки,js и html страницы на определенном сайте. Если сайт не тот что указан в настройках кеширование не производить.
     
  2. alexey-m

    alexey-m Elder - Старейшина

    Joined:
    15 Jul 2009
    Messages:
    518
    Likes Received:
    100
    Reputations:
    37
    а чем готовые решения не устраивают (squid к примеру) или надо именно свое?
     
  3. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Готовые решения не интересуют. Надо именно свое. Чтобы пользователь поставил и мог уже пользоваться. А не заморачиваться с настройками.
     
  4. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Не подскажите как сохранять подгружаемый файл через IdHttpProxyServer и как на лету подменить часть страницы?
     
  5. DYUMON

    DYUMON New Member

    Joined:
    15 Sep 2010
    Messages:
    68
    Likes Received:
    2
    Reputations:
    0
    тема тут уже была такая. ищи
     
  6. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    В общем осталась одна проблема. Подскажите как сохранить файл на диск который проходит через IndyHTTPProxyServer
     
  7. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Используй объект типа TFileStream.
     
  8. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Пробую
    Code:
      if(Pos('.gif',ADocument)>0) then
        begin
    
          Stream2 := TFileStream.Create('1.gif', fmOpenWrite);
          Stream2.Seek(0, soFromEnd);
          Stream2.CopyFrom(VStream, VStream.Size);
          Stream2.Free;
        end;
    
    Ничего не записывается... Никак не могу понять как записать файл на диск.
     
  9. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Я так понимаю, что VStream - это поток (stream)? Тогда делай
    Code:
    VStream.SaveToFile('C:\имя_файла.gif');
    Также перед этим можешь сделать
    Code:
    VStream.Position := 0;
    но не обязательно, по моему, не помню точно и немогу сейчас проверить.
    По поводу твоего кода из предыдущего поста. Если перед
    Code:
    Stream2.CopyFrom(VStream, VStream.Size);
    
    добавить
    Code:
    VStream.Position := 0;
    то также все норм должно быть.
    Строчка
    Code:
    Stream2.Seek(0, soFromEnd);
    не нужна. А зачем?
     
  10. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    1) var VStream: TStream; там нету свойства SaveToFile это первым делом смотрелось )
    2) Тоже не сработало :(
     
    #10 Rastamanka, 12 Mar 2012
    Last edited: 12 Mar 2012
  11. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Поскольку TStream - абстрактный класс, то объекты можно создавать только от наследников этого класса. То есть VStream - может быть объектом типа TMemoryStream, TStringStream и т. д., нужно смотреть по коду... Так вот если VStream - объект типа TMemoryStream, например, тогда можно записывать так:
    Code:
    TMemoryStream(VStream).SaveToFile('C:\имя_файла.gif');
    Если нет - тогда ошибка будет на этапе работы программы (нужно смотреть по коду).
     
  12. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Спасибо что помогаете после долго молчания всех в данной теме. Файл создался размером 35 байт. При попытке открыть его через тот же Paint ничего не показывает. Через текстовый редактор пробую открыть. Говорит что мол файл бинарный. Жму далее а в нем GIF89a и все )
     
  13. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Понятно. Нужно немного больше кода. Может быть где то поток перезаписывается, или не все данные в него загружаются, хотя не факт.
     
  14. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Да собственно перезаписи нигде нет. Пробую этот же код где больше ничего нет кроме как самого idhttpproxyserver.Все равно тоже самое. Сейчас вешаю это дело на событии OnHttpDocument.

    Code:
    procedure TForm1.test(ASender: TIdHTTPProxyServer; const ADocument: String;
      var VStream: TStream; const AHeaders: TIdHeaderList);
    var
     Stream2: TFileStream;
     IntBuf: array[0..9] of Integer;
    begin
    
     if(Pos('.gif',ADocument)>0) then
       begin
    
        TMemoryStream(VStream).SaveToFile('2.gif');
    
       end;
    end;
    
     
  15. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    OnHttpDocument возникает скорее всего не тогда, когда все данные прочитаны, а когда прочитана хотя бы какая то часть. То есть получается, что все данные нужно накапливать в дополнительно потоке и потом его записывать один раз в файл или же постоянно открывать файл и дописывать данные в конец. Узнать полный размер тела документа можно из заголовков (Content-length: ).

    Также в Google можно найти информацию об этом событии и еще кое-что о поле TransferMode и значении tmFullDocument. Это скорее всего именно то, что нужно.
    Code:
    http://www.delphimaster.net/view/6-1239173060
     
  16. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    В новом инди это свойство отсутствует )
     
    #16 Rastamanka, 12 Mar 2012
    Last edited: 12 Mar 2012
  17. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    В общем кое что начинает получаться. Единственное но. Файл то записывает то нет. Не могу понять в чем проблема.
    Code:
    function PosR2L(): String;
    
    
      function InvertS(const S: string): string;
    
      var
        i, Len: Integer;
      begin
        Len := Length(S);
        SetLength(Result, Len);
        for i := 1 to Len do
          Result[i] := S[Len - i + 1];
      end;
    
    var
      ps: Integer;
    begin
    
      ps := Pos(InvertS('/'), InvertS(b));
    
      if ps <> 0 then
        begin
        ps:=Length(b) - Length('/') - ps + 3;
        Result := Copy(b,ps,Length(b));
        Delete(b, ps, Length(Result) + 1);
        end  else
        Result := '0';
    end;
    
    procedure TForm1.test(ASender: TIdHTTPProxyServer; const ADocument: String;
      var VStream: TStream; const AHeaders: TIdHeaderList);
    var
    FS   :    TFileStream;
    i:String;
    begin
    
    if(Pos('.gif',ADocument)>0) or (Pos('.jpg',ADocument)>0) or (Pos('.swf',ADocument)>0) or (Pos('.js',ADocument)>0) or (Pos('.css',ADocument)>0) or (Pos('.png',ADocument)>0) or (Pos('.xml',ADocument)>0)  then
      begin
      b:=ADocument;
      i := PosR2L();
    
      b:=StringReplace(b, '/', '\',[rfReplaceAll]);
        mmo1.Lines.Add('C:\Users\carlson\Desktop\1'+b+i);
      if not DirectoryExists('C:\Users\carlson\Desktop\1'+b) then
        ForceDirectories('C:\Users\carlson\Desktop\1'+b);
    
      if not FileExists('C:\Users\carlson\Desktop\1'+b+i) then
        begin
         if (VStream.Size > 100000) then
          Begin
                ShowMessage('1');
            FS := TFileStream.Create('C:\Users\carlson\Desktop\1'+b+i, fmCreate);
            FS.CopyFrom(VStream, VStream.Size);
            FS.Free;
           End;
        end;
      end;
    end;
    
     
  18. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    937
    Likes Received:
    162
    Reputations:
    27
    Code:
    if (VStream.Size > 100000) then
    begin
    ...
    end;
     
  19. Rastamanka

    Rastamanka Elder - Старейшина

    Joined:
    26 Nov 2008
    Messages:
    429
    Likes Received:
    11
    Reputations:
    7
    Угу проблема была не в этом. А в том что заходил я на сайт через прокси тогда, когда до этого там уже был. А так как браузеры все почти кешируют данные и повторно их не загружают с инета из-за чего они через прокси не проходили )))

    Сейчас все хорошо работает кроме одного.

    В инете нашел измененный файл IndyHtppProxyServer который позволял в случае если подгружаемый файл существует на диске то брать его с диска.

    Посмотрел что там было изменено. Нашел что было добавлено.

    Code:
       procedure CommandFILE(ASender: TIdCommand);
    
     with CommandHandlers.Add do
     begin
       Command := 'FILE';            {do not localize}
       OnCommand := CommandFILE;
       ParseParams := True;
       Disconnect := true;
     end;
    
    procedure TIdHTTPProxyServer.CommandFILE( ASender: TIdCommand );
    begin
    ASender.Context.Connection.IOHandler.WriteFile(URLDecode(ASender.Params.Strings[ 0]));
    end;
    
    procedure TIdHTTPProxyServer.CommandHEAD( ASender: TIdCommand ) ;
    begin
    end;

    Встроил все это в новый Indy. Подмена прекрасно работает. Правда перед этим надо прогнать путь где лежит файл через UrlEncode.

    Файл подмениваю вот так AData := 'FILE '+URLEncode(path, false)+' HTTP/1.1' в событии OnBeforeCommandHandler.

    Но появилась одна проблема. Делалось собственно говоря это чтобы сто раз не подгружать тяжелые флешки и картинки. Но как оказалось на многие флешки передают параметры к примеру index.swf?set_backgroud=000000, а так же картинки на многих страницах имеют примерно такой вид 1.gif?45333... Но когда я пробую так же подгрузить флешку с диска с параметрами говорит что файла нет, а без параметров флешка грузиться но не срабатывает как надо потому что нету параметров. Подскажите как быть?
     
  20. xophet

    xophet Member

    Joined:
    16 Apr 2011
    Messages:
    617
    Likes Received:
    49
    Reputations:
    5
    Здесь скорее всего проблема в том, что в имени файла не может быть некоторых символов (например того же знака "?". Полный список символов: ~#%&*{}\:<>?/+|").
    придумай как сохранять без этих символов,
    и как загружать потом файл, если в его имени встретился запретный знак