Oh, it is that bug :((

Sorry for not including in the debate sooner, but I lost contact with
GpHttpProxy years ago when I started to work on a custom version for one of
my customers. Now I had no idea which of the problems I fixed years ago this
was (yes, I was not using source control at the time :( ).

The trick was to destroy remote socket and recreate it if host or port
changed.

I think this are the two most important parts:

procedure TGpHttpProxy.ProcessHeader(Client: TGpHttpProxyClient);
var
  ahost        : string;
  aport        : string;
  header       : string;
  returnContent: string;
  resetSocket  : boolean;
begin
  resetSocket := false;
  returnContent := '';
  header := Client.Received;
  if SameText(FirstEl(header,' ',-1),'CONNECT') then begin
    // TCP Tunnel proxy request
    HttpData(Client).ProxyType := ptTCPTunnel;
    if not IPSec.IsAllowed(Client.PeerAddr) then
      returnContent := Response.sTCPTunnelIPForbidden.Text
    else if not (ptTCPTunnel in EnabledTypes) then
      returnContent := Response.sTCPTunnelClosed.Text
    else if not
ProcessTCPTunnelHeader(Client,header,ahost,aport,returnContent) then
      returnContent := Response.sTCPTunnelBadRequest.Text;
  end
  else begin
    // HTTP proxy request
    HttpData(Client).ProxyType := ptHTTP;
    if not IPSec.IsAllowed(Client.PeerAddr) then
      returnContent := Response.sHTTPIPForbidden.Text
    else if not (ptHTTP in EnabledTypes) then
      returnContent := Response.sHTTPClosed.Text
    else if not
ProcessHTTPHeader(Client,header,ahost,aport,returnContent,resetSocket) then
      returnContent := Response.sHTTPBadRequest.Text;
  end; //else SameText()
  // Header parsed, create remote socket.
  if returnContent = '' then begin
    if resetSocket then begin
      {$IFDEF LogHttpFlow}
      LogFlow(Client, 'Destroyed connection to %s:%s due to host/port
change',
        [Client.RemoteHost, Client.RemoteSocket.Port]);
      {$ENDIF LogHttpFlow}
      Client.DestroyRemoteSocket;
      Client.NumRequests := 1;
    end;
    if not assigned(Client.RemoteSocket) then with Client do begin
      {$IFDEF LogHttpFlow}
      LogFlow(Client, 'Opening connection to %s:%s', [ahost, aport]);
      {$ENDIF LogHttpFlow}
      CreateRemoteSocket;
      RemoteHost            := ahost;
      RemoteSocket.Port     := aport;
      RemoteSocket.LineMode := false;
      HookRemoteEvents(RemoteSocket);
      RemoteSocket.DnsLookup(ahost);
      DoRemoteSocketPrepared(Client);
    end //with/if
    else begin
      {$IFDEF LogHttpFlow}
      LogFlow(Client, 'Reusing connection to %s:%s', [Client.RemoteHost,
        Client.RemoteSocket.Port]);
      {$ENDIF LogHttpFlow}
    end;
    {$IFDEF LogHttpFlow}
    LogFlow(Client, 'Request: %s', [FirstEl(header, #13, -1)]);
    {$ENDIF LogHttpFlow}
    Client.Received := header;
  end
  else begin
    Client.DestroyRemoteSocket;
    Client.RemoteContent := returnContent;
  end;
  Client.GotHeader := true;
end; { TGpHttpProxy.ProcessHeader }

function TGpHttpProxy.ProcessHTTPHeader(Client: TGpHttpProxyClient; var
header, ahost,
  aport, returnContent: string; var socketResetRequired: boolean): boolean;

  function MakeUrl(aproto, auser, apass, ahost, aport, apath: string):
string;
  begin
    Result := aproto;
    if Last(Result,1) = ':' then
      Result := Result + '//'
    else if Last(Result,1) <> '/' then
      Result := Result + '://';
    if auser <> '' then begin
      Result := Result + auser;
      if apass <> '' then
        Result := Result + ':' + apass;
      Result := Result + '@';
    end;
    Result := Result + ahost;
    if (aport <> '') and (aport <> '80') then
      Result := Result + ':' + aport;
    Result := Result + apath;
  end; { MakeUrl }

var
  apass             : string;
  apath             : string;
  aproto            : string;
  auser             : string;
  command           : string;
  hdrHost           : string;
  ignoreNextHopProxy: boolean;
  p1                : integer;
  p2                : integer;
  s                 : string;
  url               : string;

begin { TGpHttpProxy.ProcessHTTPHeader }
  Result := false;
  socketResetRequired := false;
  // extract url from GET/POST header
  s := header;
  p1 := Pos(' ',s);
  if p1 > 0 then begin
    command := First(s,p1-1);
    Delete(s,1,p1);
    s := TrimLeft(s);
    p2 := Pos(' ',s);
    if p2 > 0 then begin
      url := Copy(s,1,p2-1);
      ParseURL(url,aproto,auser,apass,ahost,aport,apath);
      if aport = '' then
        aport := '80';
      hdrHost := ExtractHeader(header,'Host');
      returnContent := '';
      ignoreNextHopProxy := false;
 
DoClientHeaderAvailable(Client,url,header,aproto,auser,apass,ahost,aport,
        apath,hdrHost,ignoreNextHopProxy,returnContent);
      if (NextHopHTTP.Address <> '') and (not ignoreNextHopProxy) and
         (returnContent = '') then //replace host information with proxy
      begin
        Delete(header,p1+1,p2-1);
        Insert(MakeUrl(aproto,auser,apass,ahost,aport,apath),header,p1+1);
        if NextHopHTTP.Username <> '' then begin
          // Insert 'Proxy-Authorization' header
          p1 := Pos(CRLF+CRLF,header);
          Insert(CRLF+'Proxy-Authorization: Basic '+
            EncodeStr(encBase64,
NextHopHTTP.Username+':'+NextHopHTTP.Password),
            header,p1);
        end;
        ReplaceHeader(header,'Host',hdrHost);
        aport := IntToStr(FNextHopProxy[ptHTTP].Port);
        ahost := FNextHopProxy[ptHTTP].Address;
        Client.UsingNextHop := true;
      end
      else if SameText(command,'OPTIONS') and (ahost = '*') then
        Exit
      else begin
        socketResetRequired :=
          assigned(Client.RemoteSocket) and
          ((not SameText(Client.RemoteHost, ahost)) or
           (Client.RemoteSocket.Port <> aport));
        // Any of the URL parts may have changed in the event handler -
modify the header.
        Delete(header,p1+1,p2-1);
        if SameText(command,'OPTIONS') then
          Insert('*', header, p1+1)
        else if ((Client.NumRequests <= 1) and (Pos('HTTP/1.0',
FirstEl(header, #13, -1)) > 0)) or socketResetRequired then
          Insert(apath, header, p1+1)
        else
          Insert(aproto+'://'+ahost+IFF(aport<>'80',':'+aport,'')+apath,
header, p1+1);
        ReplaceHeader(header, 'Host', hdrHost);
        if auser <> '' then begin
          // Insert 'Authorization' header
          p1 := Pos(CRLF+CRLF,header);
          Insert(CRLF+'Authorization: Basic '+EncodeStr(encBase64, auser+
':'+apass),
            header,p1);
        end;
        Client.ProxyConnection := ExtractHeader(header, 'Proxy-connection');
        Client.UsingNextHop := false;
      end;
      Result := true;
    end; //else p2 > 0
  end; //else p1 > 0
end; { TGpHttpProxy.ProcessHTTPHeader }

Hope that helps.

Primoz

-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On
Behalf Of S.Korotky
Sent: Sunday, September 21, 2008 9:56 PM
To: ICS support mailing
Subject: Re: [twsocket] GpHTTPProxy doesn't work correctly

Hello Stephane,

Yes, I've managed to locate the place where the problems are "initiated",
this
is ProcessHeader procedure. It processes only the very first http-header in
an established connection and bypasses all the others. So, if a browser
keeps the connections and uses them to request pages from different sites,
404 errors are produced or incorrect content is shown. I don't think
it will be easy to write a quick patch without proper processing of http 1.1
data on per-document basis. Perhaps, if it'll be possible to make a browser
believe, that it is _not_ connected to a proxy, it will not re-use the same
connection for different sites, but will establish new ones. I don't
remember if a http-header exists which allows for doing so, if included in
http response header to the browser (this is not the thing the
Proxy-Connection does).

Best wishes
Stanislav Korotky

----- Original Message ----- 
From: "Stéphane CHADEYRON" <[EMAIL PROTECTED]>
To: "ICS support mailing" <twsocket@elists.org>
Sent: Saturday, September 20, 2008 10:03 PM
Subject: Re: [twsocket] GpHTTPProxy doesn't work correctly


> Hello Stanislav,
>
> I have a user case: with the web-site :www.youtube.com
> Impossible display this web site correct.
>
> Other case but not systematic:
> 1. write in the address bar in your navigator (with the proxy) the url:
> www.google.com
> 2. write in the address bar in your navigator (with the proxy) the url:
> www.clubic.com
> 3. write again in the address bar in your navigator (with the proxy) the
> url: www.clubic.com
> > result: there is a other page... google or smartserver or error...
>
> Thank you for your help.
>
> Best regards,
>
> Stephan
>
> -- 
> To unsubscribe or change your settings for TWSocket mailing list
> please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
> Visit our website at http://www.overbyte.be
>

-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

-- 
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to