THRIFT-4841 THTTPTransport relies on activeX component
Client: Delphi
Patch: Jens Geyer

This closes #1778
diff --git a/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas
new file mode 100644
index 0000000..cdfb541
--- /dev/null
+++ b/lib/delphi/src/Thrift.Transport.MsxmlHTTP.pas
@@ -0,0 +1,255 @@
+(*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *)
+unit Thrift.Transport.MsxmlHTTP;
+
+{$I Thrift.Defines.inc}
+{$SCOPEDENUMS ON}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  Math,
+  Generics.Collections,
+  {$IFDEF OLD_UNIT_NAMES}
+    ActiveX, msxml,
+  {$ELSE}
+    Winapi.ActiveX, Winapi.msxml,
+  {$ENDIF}
+  Thrift.Collections,
+  Thrift.Transport,
+  Thrift.Exception,
+  Thrift.Utils,
+  Thrift.Stream;
+
+type
+  TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient)
+  private
+    FUri : string;
+    FInputStream : IThriftStream;
+    FOutputStream : IThriftStream;
+    FDnsResolveTimeout : Integer;
+    FConnectionTimeout : Integer;
+    FSendTimeout : Integer;
+    FReadTimeout : Integer;
+    FCustomHeaders : IThriftDictionary<string,string>;
+
+    function CreateRequest: IXMLHTTPRequest;
+  protected
+    function GetIsOpen: Boolean; override;
+    procedure Open(); override;
+    procedure Close(); override;
+    function  Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
+    procedure Write( const pBuf : Pointer; off, len : Integer); override;
+    procedure Flush; override;
+
+    procedure SetDnsResolveTimeout(const Value: Integer);
+    function GetDnsResolveTimeout: Integer;
+    procedure SetConnectionTimeout(const Value: Integer);
+    function GetConnectionTimeout: Integer;
+    procedure SetSendTimeout(const Value: Integer);
+    function GetSendTimeout: Integer;
+    procedure SetReadTimeout(const Value: Integer);
+    function GetReadTimeout: Integer;
+
+    function GetCustomHeaders: IThriftDictionary<string,string>;
+    procedure SendRequest;
+    property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
+    property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
+    property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
+    property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
+    property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
+  public
+    constructor Create( const AUri: string);
+    destructor Destroy; override;
+  end;
+
+
+implementation
+
+
+{ TMsxmlHTTPClientImpl }
+
+constructor TMsxmlHTTPClientImpl.Create(const AUri: string);
+begin
+  inherited Create;
+  FUri := AUri;
+
+  // defaults according to MSDN
+  FDnsResolveTimeout := 0; // no timeout
+  FConnectionTimeout := 60 * 1000;
+  FSendTimeout       := 30 * 1000;
+  FReadTimeout       := 30 * 1000;
+
+  FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
+  FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
+end;
+
+function TMsxmlHTTPClientImpl.CreateRequest: IXMLHTTPRequest;
+var
+  pair : TPair<string,string>;
+  srvHttp : IServerXMLHTTPRequest;
+begin
+  {$IF CompilerVersion >= 21.0}
+  Result := CoServerXMLHTTP.Create;
+  {$ELSE}
+  Result := CoXMLHTTPRequest.Create;
+  {$IFEND}
+
+  // setting a timeout value to 0 (zero) means "no timeout" for that setting
+  if Supports( result, IServerXMLHTTPRequest, srvHttp)
+  then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout);
+
+  Result.open('POST', FUri, False, '', '');
+  Result.setRequestHeader( 'Content-Type', 'application/x-thrift');
+  Result.setRequestHeader( 'Accept', 'application/x-thrift');
+  Result.setRequestHeader( 'User-Agent', 'Delphi/IHTTPClient');
+
+  for pair in FCustomHeaders do begin
+    Result.setRequestHeader( pair.Key, pair.Value );
+  end;
+end;
+
+destructor TMsxmlHTTPClientImpl.Destroy;
+begin
+  Close;
+  inherited;
+end;
+
+function TMsxmlHTTPClientImpl.GetDnsResolveTimeout: Integer;
+begin
+  Result := FDnsResolveTimeout;
+end;
+
+procedure TMsxmlHTTPClientImpl.SetDnsResolveTimeout(const Value: Integer);
+begin
+  FDnsResolveTimeout := Value;
+end;
+
+function TMsxmlHTTPClientImpl.GetConnectionTimeout: Integer;
+begin
+  Result := FConnectionTimeout;
+end;
+
+procedure TMsxmlHTTPClientImpl.SetConnectionTimeout(const Value: Integer);
+begin
+  FConnectionTimeout := Value;
+end;
+
+function TMsxmlHTTPClientImpl.GetSendTimeout: Integer;
+begin
+  Result := FSendTimeout;
+end;
+
+procedure TMsxmlHTTPClientImpl.SetSendTimeout(const Value: Integer);
+begin
+  FSendTimeout := Value;
+end;
+
+function TMsxmlHTTPClientImpl.GetReadTimeout: Integer;
+begin
+  Result := FReadTimeout;
+end;
+
+procedure TMsxmlHTTPClientImpl.SetReadTimeout(const Value: Integer);
+begin
+  FReadTimeout := Value;
+end;
+
+function TMsxmlHTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
+begin
+  Result := FCustomHeaders;
+end;
+
+function TMsxmlHTTPClientImpl.GetIsOpen: Boolean;
+begin
+  Result := True;
+end;
+
+procedure TMsxmlHTTPClientImpl.Open;
+begin
+  FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
+end;
+
+procedure TMsxmlHTTPClientImpl.Close;
+begin
+  FInputStream := nil;
+  FOutputStream := nil;
+end;
+
+procedure TMsxmlHTTPClientImpl.Flush;
+begin
+  try
+    SendRequest;
+  finally
+    FOutputStream := nil;
+    FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
+    ASSERT( FOutputStream <> nil);
+  end;
+end;
+
+function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
+begin
+  if FInputStream = nil then begin
+    raise TTransportExceptionNotOpen.Create('No request has been sent');
+  end;
+
+  try
+    Result := FInputStream.Read( pBuf, buflen, off, len)
+  except
+    on E: Exception
+    do raise TTransportExceptionUnknown.Create(E.Message);
+  end;
+end;
+
+procedure TMsxmlHTTPClientImpl.SendRequest;
+var
+  xmlhttp : IXMLHTTPRequest;
+  ms : TMemoryStream;
+  a : TBytes;
+  len : Integer;
+begin
+  xmlhttp := CreateRequest;
+
+  ms := TMemoryStream.Create;
+  try
+    a := FOutputStream.ToArray;
+    len := Length(a);
+    if len > 0 then begin
+      ms.WriteBuffer( Pointer(@a[0])^, len);
+    end;
+    ms.Position := 0;
+    xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference )));
+    FInputStream := nil;
+    FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream);
+  finally
+    ms.Free;
+  end;
+end;
+
+procedure TMsxmlHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer);
+begin
+  FOutputStream.Write( pBuf, off, len);
+end;
+
+
+
+end.
+
diff --git a/lib/delphi/src/Thrift.Transport.WinHTTP.pas b/lib/delphi/src/Thrift.Transport.WinHTTP.pas
new file mode 100644
index 0000000..aac2aea
--- /dev/null
+++ b/lib/delphi/src/Thrift.Transport.WinHTTP.pas
@@ -0,0 +1,335 @@
+(*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *)
+unit Thrift.Transport.WinHTTP;
+
+{$I Thrift.Defines.inc}
+{$SCOPEDENUMS ON}
+
+interface
+
+uses
+  Classes,
+  SysUtils,
+  Math,
+  Generics.Collections,
+  Thrift.Collections,
+  Thrift.Transport,
+  Thrift.Exception,
+  Thrift.Utils,
+  Thrift.WinHTTP,
+  Thrift.Stream;
+
+type
+  TWinHTTPClientImpl = class( TTransportImpl, IHTTPClient)
+  private
+    FUri : string;
+    FInputStream : IThriftStream;
+    FOutputMemoryStream : TMemoryStream;
+    FDnsResolveTimeout : Integer;
+    FConnectionTimeout : Integer;
+    FSendTimeout : Integer;
+    FReadTimeout : Integer;
+    FCustomHeaders : IThriftDictionary<string,string>;
+
+    function CreateRequest: IWinHTTPRequest;
+
+  private type
+      THTTPResponseStream = class( TThriftStreamImpl)
+      private
+        FRequest : IWinHTTPRequest;
+      protected
+        procedure Write( const pBuf : Pointer; offset: Integer; count: Integer); override;
+        function Read( const pBuf : Pointer; const buflen : Integer; offset: Integer; count: Integer): Integer; override;
+        procedure Open; override;
+        procedure Close; override;
+        procedure Flush; override;
+        function IsOpen: Boolean; override;
+        function ToArray: TBytes; override;
+      public
+        constructor Create( const aRequest : IWinHTTPRequest);
+        destructor Destroy; override;
+      end;
+
+  protected
+    function GetIsOpen: Boolean; override;
+    procedure Open(); override;
+    procedure Close(); override;
+    function  Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
+    procedure Write( const pBuf : Pointer; off, len : Integer); override;
+    procedure Flush; override;
+
+    procedure SetDnsResolveTimeout(const Value: Integer);
+    function GetDnsResolveTimeout: Integer;
+    procedure SetConnectionTimeout(const Value: Integer);
+    function GetConnectionTimeout: Integer;
+    procedure SetSendTimeout(const Value: Integer);
+    function GetSendTimeout: Integer;
+    procedure SetReadTimeout(const Value: Integer);
+    function GetReadTimeout: Integer;
+
+    function GetCustomHeaders: IThriftDictionary<string,string>;
+    procedure SendRequest;
+    property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
+    property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
+    property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
+    property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
+    property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
+  public
+    constructor Create( const AUri: string);
+    destructor Destroy; override;
+  end;
+
+implementation
+
+
+{ TWinHTTPClientImpl }
+
+constructor TWinHTTPClientImpl.Create(const AUri: string);
+begin
+  inherited Create;
+  FUri := AUri;
+
+  // defaults according to MSDN
+  FDnsResolveTimeout := 0; // no timeout
+  FConnectionTimeout := 60 * 1000;
+  FSendTimeout       := 30 * 1000;
+  FReadTimeout       := 30 * 1000;
+
+  FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
+  FOutputMemoryStream := TMemoryStream.Create;
+end;
+
+destructor TWinHTTPClientImpl.Destroy;
+begin
+  Close;
+  FreeAndNil( FOutputMemoryStream);
+  inherited;
+end;
+
+function TWinHTTPClientImpl.CreateRequest: IWinHTTPRequest;
+var
+  pair : TPair<string,string>;
+  session : IWinHTTPSession;
+  connect : IWinHTTPConnection;
+  url     : IWinHTTPUrl;
+  sPath   : string;
+begin
+  url := TWinHTTPUrlImpl.Create( FUri);
+
+  session := TWinHTTPSessionImpl.Create('Apache Thrift Delphi Client');
+  connect := session.Connect( url.HostName, url.Port);
+
+  sPath   := url.UrlPath + url.ExtraInfo;
+  result  := connect.OpenRequest( (url.Scheme = 'https'), 'POST', sPath, 'application/x-thrift');
+
+  // setting a timeout value to 0 (zero) means "no timeout" for that setting
+  result.SetTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout);
+
+  result.AddRequestHeader( 'Content-Type: application/x-thrift', WINHTTP_ADDREQ_FLAG_ADD);
+
+  for pair in FCustomHeaders do begin
+    Result.AddRequestHeader( pair.Key +': '+ pair.Value, WINHTTP_ADDREQ_FLAG_ADD);
+  end;
+end;
+
+function TWinHTTPClientImpl.GetDnsResolveTimeout: Integer;
+begin
+  Result := FDnsResolveTimeout;
+end;
+
+procedure TWinHTTPClientImpl.SetDnsResolveTimeout(const Value: Integer);
+begin
+  FDnsResolveTimeout := Value;
+end;
+
+function TWinHTTPClientImpl.GetConnectionTimeout: Integer;
+begin
+  Result := FConnectionTimeout;
+end;
+
+procedure TWinHTTPClientImpl.SetConnectionTimeout(const Value: Integer);
+begin
+  FConnectionTimeout := Value;
+end;
+
+function TWinHTTPClientImpl.GetSendTimeout: Integer;
+begin
+  Result := FSendTimeout;
+end;
+
+procedure TWinHTTPClientImpl.SetSendTimeout(const Value: Integer);
+begin
+  FSendTimeout := Value;
+end;
+
+function TWinHTTPClientImpl.GetReadTimeout: Integer;
+begin
+  Result := FReadTimeout;
+end;
+
+procedure TWinHTTPClientImpl.SetReadTimeout(const Value: Integer);
+begin
+  FReadTimeout := Value;
+end;
+
+function TWinHTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
+begin
+  Result := FCustomHeaders;
+end;
+
+function TWinHTTPClientImpl.GetIsOpen: Boolean;
+begin
+  Result := True;
+end;
+
+procedure TWinHTTPClientImpl.Open;
+begin
+  FreeAndNil( FOutputMemoryStream);
+  FOutputMemoryStream := TMemoryStream.Create;
+end;
+
+procedure TWinHTTPClientImpl.Close;
+begin
+  FInputStream := nil;
+  FreeAndNil( FOutputMemoryStream);
+end;
+
+procedure TWinHTTPClientImpl.Flush;
+begin
+  try
+    SendRequest;
+  finally
+    FreeAndNil( FOutputMemoryStream);
+    FOutputMemoryStream := TMemoryStream.Create;
+    ASSERT( FOutputMemoryStream <> nil);
+  end;
+end;
+
+function TWinHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
+begin
+  if FInputStream = nil then begin
+    raise TTransportExceptionNotOpen.Create('No request has been sent');
+  end;
+
+  try
+    Result := FInputStream.Read( pBuf, buflen, off, len)
+  except
+    on E: Exception
+    do raise TTransportExceptionUnknown.Create(E.Message);
+  end;
+end;
+
+procedure TWinHTTPClientImpl.SendRequest;
+var
+  http : IWinHTTPRequest;
+  pData : PByte;
+  len : Integer;
+begin
+  http := CreateRequest;
+
+  pData := FOutputMemoryStream.Memory;
+  len   := FOutputMemoryStream.Size;
+
+  // send all data immediately, since we have it in memory
+  if not http.SendRequest( pData, len, 0)
+  then raise TTransportExceptionUnknown.Create('send request error');
+
+  // end request and start receiving
+  if not http.FlushAndReceiveResponse
+  then raise TTransportExceptionInterrupted.Create('flush/receive error');
+
+  FInputStream := THTTPResponseStream.Create(http);
+end;
+
+procedure TWinHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer);
+var pTmp : PByte;
+begin
+  pTmp := pBuf;
+  Inc(pTmp,off);
+  FOutputMemoryStream.Write( pTmp^, len);
+end;
+
+
+{ TWinHTTPClientImpl.THTTPResponseStream }
+
+constructor TWinHTTPClientImpl.THTTPResponseStream.Create( const aRequest : IWinHTTPRequest);
+begin
+  inherited Create;
+  FRequest := aRequest;
+end;
+
+destructor TWinHTTPClientImpl.THTTPResponseStream.Destroy;
+begin
+  try
+    Close;
+  finally
+    inherited Destroy;
+  end;
+end;
+
+procedure TWinHTTPClientImpl.THTTPResponseStream.Close;
+begin
+  FRequest := nil;
+end;
+
+procedure TWinHTTPClientImpl.THTTPResponseStream.Flush;
+begin
+  raise ENotImplemented(ClassName+'.Flush');
+end;
+
+function TWinHTTPClientImpl.THTTPResponseStream.IsOpen: Boolean;
+begin
+  Result := FRequest <> nil;
+end;
+
+procedure TWinHTTPClientImpl.THTTPResponseStream.Open;
+begin
+  // nothing to do
+end;
+
+procedure TWinHTTPClientImpl.THTTPResponseStream.Write(const pBuf : Pointer; offset, count: Integer);
+begin
+  inherited;  // check pointers
+  raise ENotImplemented(ClassName+'.Write');
+end;
+
+function TWinHTTPClientImpl.THTTPResponseStream.Read(const pBuf : Pointer; const buflen : Integer; offset, count: Integer): Integer;
+var pTmp : PByte;
+begin
+  inherited;  // check pointers
+
+  if count >= buflen-offset
+  then count := buflen-offset;
+
+  if count > 0 then begin
+    pTmp   := pBuf;
+    Inc( pTmp, offset);
+    Result := FRequest.ReadData( pTmp, count);
+    ASSERT( Result >= 0);
+  end
+  else Result := 0;
+end;
+
+function TWinHTTPClientImpl.THTTPResponseStream.ToArray: TBytes;
+begin
+  raise ENotImplemented(ClassName+'.ToArray');
+end;
+
+
+end.
diff --git a/lib/delphi/src/Thrift.Transport.pas b/lib/delphi/src/Thrift.Transport.pas
index dad9ab7..1f8fdb0 100644
--- a/lib/delphi/src/Thrift.Transport.pas
+++ b/lib/delphi/src/Thrift.Transport.pas
@@ -29,9 +29,9 @@
   Math,
   Generics.Collections,
   {$IFDEF OLD_UNIT_NAMES}
-    ActiveX, msxml, WinSock, Sockets,
+    WinSock, Sockets,
   {$ELSE}
-    Winapi.ActiveX, Winapi.msxml, Winapi.WinSock,
+    Winapi.WinSock,
     {$IFDEF OLD_SOCKETS}
       Web.Win.Sockets,
     {$ELSE}
@@ -41,6 +41,7 @@
   Thrift.Collections,
   Thrift.Exception,
   Thrift.Utils,
+  Thrift.WinHTTP,
   Thrift.Stream;
 
 type
@@ -137,47 +138,6 @@
     property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
   end;
 
-  THTTPClientImpl = class( TTransportImpl, IHTTPClient)
-  private
-    FUri : string;
-    FInputStream : IThriftStream;
-    FOutputStream : IThriftStream;
-    FDnsResolveTimeout : Integer;
-    FConnectionTimeout : Integer;
-    FSendTimeout : Integer;
-    FReadTimeout : Integer;
-    FCustomHeaders : IThriftDictionary<string,string>;
-
-    function CreateRequest: IXMLHTTPRequest;
-  protected
-    function GetIsOpen: Boolean; override;
-    procedure Open(); override;
-    procedure Close(); override;
-    function  Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
-    procedure Write( const pBuf : Pointer; off, len : Integer); override;
-    procedure Flush; override;
-
-    procedure SetDnsResolveTimeout(const Value: Integer);
-    function GetDnsResolveTimeout: Integer;
-    procedure SetConnectionTimeout(const Value: Integer);
-    function GetConnectionTimeout: Integer;
-    procedure SetSendTimeout(const Value: Integer);
-    function GetSendTimeout: Integer;
-    procedure SetReadTimeout(const Value: Integer);
-    function GetReadTimeout: Integer;
-
-    function GetCustomHeaders: IThriftDictionary<string,string>;
-    procedure SendRequest;
-    property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
-    property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
-    property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
-    property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
-    property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
-  public
-    constructor Create( const AUri: string);
-    destructor Destroy; override;
-  end;
-
   IServerTransport = interface
     ['{C43B87ED-69EA-47C4-B77C-15E288252900}']
     procedure Listen;
@@ -472,170 +432,6 @@
   Self.Write( pBuf, 0, len);
 end;
 
-{ THTTPClientImpl }
-
-constructor THTTPClientImpl.Create(const AUri: string);
-begin
-  inherited Create;
-  FUri := AUri;
-
-  // defaults according to MSDN
-  FDnsResolveTimeout := 0; // no timeout
-  FConnectionTimeout := 60 * 1000;
-  FSendTimeout       := 30 * 1000;
-  FReadTimeout       := 30 * 1000;
-
-  FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
-  FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
-end;
-
-function THTTPClientImpl.CreateRequest: IXMLHTTPRequest;
-var
-  pair : TPair<string,string>;
-  srvHttp : IServerXMLHTTPRequest;
-begin
-  {$IF CompilerVersion >= 21.0}
-  Result := CoServerXMLHTTP.Create;
-  {$ELSE}
-  Result := CoXMLHTTPRequest.Create;
-  {$IFEND}
-
-  // setting a timeout value to 0 (zero) means "no timeout" for that setting
-  if Supports( result, IServerXMLHTTPRequest, srvHttp)
-  then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout);
-
-  Result.open('POST', FUri, False, '', '');
-  Result.setRequestHeader( 'Content-Type', 'application/x-thrift');
-  Result.setRequestHeader( 'Accept', 'application/x-thrift');
-  Result.setRequestHeader( 'User-Agent', 'Delphi/IHTTPClient');
-
-  for pair in FCustomHeaders do begin
-    Result.setRequestHeader( pair.Key, pair.Value );
-  end;
-end;
-
-destructor THTTPClientImpl.Destroy;
-begin
-  Close;
-  inherited;
-end;
-
-function THTTPClientImpl.GetDnsResolveTimeout: Integer;
-begin
-  Result := FDnsResolveTimeout;
-end;
-
-procedure THTTPClientImpl.SetDnsResolveTimeout(const Value: Integer);
-begin
-  FDnsResolveTimeout := Value;
-end;
-
-function THTTPClientImpl.GetConnectionTimeout: Integer;
-begin
-  Result := FConnectionTimeout;
-end;
-
-procedure THTTPClientImpl.SetConnectionTimeout(const Value: Integer);
-begin
-  FConnectionTimeout := Value;
-end;
-
-function THTTPClientImpl.GetSendTimeout: Integer;
-begin
-  Result := FSendTimeout;
-end;
-
-procedure THTTPClientImpl.SetSendTimeout(const Value: Integer);
-begin
-  FSendTimeout := Value;
-end;
-
-function THTTPClientImpl.GetReadTimeout: Integer;
-begin
-  Result := FReadTimeout;
-end;
-
-procedure THTTPClientImpl.SetReadTimeout(const Value: Integer);
-begin
-  FReadTimeout := Value;
-end;
-
-function THTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
-begin
-  Result := FCustomHeaders;
-end;
-
-function THTTPClientImpl.GetIsOpen: Boolean;
-begin
-  Result := True;
-end;
-
-procedure THTTPClientImpl.Open;
-begin
-  FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
-end;
-
-procedure THTTPClientImpl.Close;
-begin
-  FInputStream := nil;
-  FOutputStream := nil;
-end;
-
-procedure THTTPClientImpl.Flush;
-begin
-  try
-    SendRequest;
-  finally
-    FOutputStream := nil;
-    FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
-    ASSERT( FOutputStream <> nil);
-  end;
-end;
-
-function THTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
-begin
-  if FInputStream = nil then begin
-    raise TTransportExceptionNotOpen.Create('No request has been sent');
-  end;
-
-  try
-    Result := FInputStream.Read( pBuf, buflen, off, len)
-  except
-    on E: Exception
-    do raise TTransportExceptionUnknown.Create(E.Message);
-  end;
-end;
-
-procedure THTTPClientImpl.SendRequest;
-var
-  xmlhttp : IXMLHTTPRequest;
-  ms : TMemoryStream;
-  a : TBytes;
-  len : Integer;
-begin
-  xmlhttp := CreateRequest;
-
-  ms := TMemoryStream.Create;
-  try
-    a := FOutputStream.ToArray;
-    len := Length(a);
-    if len > 0 then begin
-      ms.WriteBuffer( Pointer(@a[0])^, len);
-    end;
-    ms.Position := 0;
-    xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference )));
-    FInputStream := nil;
-    FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream);
-  finally
-    ms.Free;
-  end;
-end;
-
-procedure THTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer);
-begin
-  FOutputStream.Write( pBuf, off, len);
-end;
-
 { TTransportException }
 
 function TTransportException.GetType: TExceptionType;
diff --git a/lib/delphi/src/Thrift.WinHTTP.pas b/lib/delphi/src/Thrift.WinHTTP.pas
new file mode 100644
index 0000000..0d824b6
--- /dev/null
+++ b/lib/delphi/src/Thrift.WinHTTP.pas
@@ -0,0 +1,805 @@
+(*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *)
+unit Thrift.WinHTTP;
+
+{$I Thrift.Defines.inc}
+{$SCOPEDENUMS ON}
+
+// packing according to winhttp.h
+{$IFDEF Win64} {$ALIGN 8} {$ELSE} {$ALIGN 4} {$ENDIF}
+
+interface
+
+uses
+  Windows,
+  Classes,
+  SysUtils,
+  Math,
+  Generics.Collections;
+
+
+type
+  HINTERNET = type Pointer;
+  INTERNET_PORT = type WORD;
+  INTERNET_SCHEME = type Integer;
+  LPLPCWSTR = ^LPCWSTR;
+
+  LPURL_COMPONENTS = ^URL_COMPONENTS;
+  URL_COMPONENTS = record
+    dwStructSize      : DWORD;              // set to SizeOf(URL_COMPONENTS)
+    lpszScheme        : LPWSTR;             // scheme name
+    dwSchemeLength    : DWORD;
+    nScheme           : INTERNET_SCHEME;    // enumerated scheme type
+    lpszHostName      : LPWSTR;             // host name
+    dwHostNameLength  : DWORD;
+    nPort             : INTERNET_PORT;      // port number
+    lpszUserName      : LPWSTR;             // user name
+    dwUserNameLength  : DWORD;
+    lpszPassword      : LPWSTR;             // password
+    dwPasswordLength  : DWORD;
+    lpszUrlPath       : LPWSTR;             // URL-path
+    dwUrlPathLength   : DWORD;
+    lpszExtraInfo     : LPWSTR;             // extra information
+    dwExtraInfoLength : DWORD;
+  end;
+
+  URL_COMPONENTSW = URL_COMPONENTS;
+  LPURL_COMPONENTSW = LPURL_COMPONENTS;
+
+
+function WinHttpCloseHandle( aHandle : HINTERNET) : BOOL;  stdcall;
+
+function WinHttpOpen( const pszAgentW       : LPCWSTR;
+                      const dwAccessType    : DWORD;
+                      const pszProxyW       : LPCWSTR;
+                      const pszProxyBypassW : LPCWSTR;
+                      const dwFlags         : DWORD
+                      ) : HINTERNET;  stdcall;
+
+function WinHttpConnect( const hSession : HINTERNET;
+                         const pswzServerName : LPCWSTR;
+                         const nServerPort : INTERNET_PORT;
+                         const dwReserved : DWORD
+                         ) : HINTERNET;  stdcall;
+
+function WinHttpOpenRequest( const hConnect : HINTERNET;
+                             const pwszVerb, pwszObjectName, pwszVersion, pwszReferrer : LPCWSTR;
+                             const ppwszAcceptTypes : LPLPCWSTR;
+                             const dwFlags : DWORD
+                             ) : HINTERNET;  stdcall;
+
+function WinHttpSetTimeouts( const hRequestOrSession : HINTERNET;
+                             const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32
+                             ) : BOOL;  stdcall;
+
+function WinHttpAddRequestHeaders( const hRequest : HINTERNET;
+                                   const pwszHeaders : LPCWSTR;
+                                   const dwHeadersLengthInChars : DWORD;
+                                   const dwModifiers : DWORD
+                                   ) : BOOL;  stdcall;
+
+function WinHttpSendRequest( const hRequest : HINTERNET;
+                             const lpszHeaders : LPCWSTR;
+                             const dwHeadersLength : DWORD;
+                             const lpOptional : Pointer;
+                             const dwOptionalLength : DWORD;
+                             const dwTotalLength : DWORD;
+                             const pContext : Pointer
+                             ) : BOOL;  stdcall;
+
+function WinHttpWriteData( const hRequest : HINTERNET;
+                           const pBuf : Pointer;
+                           const dwBytesToWrite : DWORD;
+                           out dwBytesWritten : DWORD
+                           ) : BOOL;  stdcall;
+
+function WinHttpReceiveResponse( const hRequest : HINTERNET; const lpReserved : Pointer) : BOOL;  stdcall;
+
+function WinHttpQueryHeaders( const hRequest     : HINTERNET;
+                              const dwInfoLevel  : DWORD;
+                              const pwszName     : LPCWSTR;
+                              const lpBuffer     : Pointer;
+                              var dwBufferLength : DWORD;
+                              var dwIndex        : DWORD
+                              ) : BOOL;  stdcall;
+
+function WinHttpQueryDataAvailable( const hRequest     : HINTERNET;
+                                    var dwNumberOfBytesAvailable : DWORD
+                                    ) : BOOL;  stdcall;
+
+function WinHttpReadData( const hRequest      : HINTERNET;
+                          const lpBuffer      : Pointer;
+                          const dwBytesToRead : DWORD;
+                          out dwBytesRead     : DWORD
+                          ) : BOOL;  stdcall;
+
+function WinHttpCrackUrl( const pwszUrl : LPCWSTR;
+                          const dwUrlLength : DWORD;
+                          const dwFlags : DWORD;
+                          var urlComponents : URL_COMPONENTS
+                          ) : BOOL;  stdcall;
+
+function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS;
+                           const dwFlags : DWORD;
+                           const pwszUrl : LPCWSTR;
+                           var pdwUrlLength : DWORD
+                          ) : BOOL;  stdcall;
+
+
+const
+  // WinHttpOpen dwAccessType values
+  WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0;
+  WINHTTP_ACCESS_TYPE_NO_PROXY      = 1;
+  WINHTTP_ACCESS_TYPE_NAMED_PROXY   = 3;
+
+  // flags for WinHttpOpen():
+  WINHTTP_FLAG_ASYNC = $10000000;  // want async session, requires WinHttpSetStatusCallback() usage
+
+  // ports
+  INTERNET_DEFAULT_PORT = 0;           // use the protocol-specific default (80 or 443)
+
+  // flags for WinHttpOpenRequest():
+  WINHTTP_FLAG_SECURE                = $00800000;  // use SSL if applicable (HTTPS)
+  WINHTTP_FLAG_ESCAPE_PERCENT        = $00000004;  // if escaping enabled, escape percent as well
+  WINHTTP_FLAG_NULL_CODEPAGE         = $00000008;  // assume all symbols are ASCII, use fast convertion
+  WINHTTP_FLAG_BYPASS_PROXY_CACHE    = $00000100; // add "pragma: no-cache" request header
+  WINHTTP_FLAG_REFRESH               = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
+  WINHTTP_FLAG_ESCAPE_DISABLE        = $00000040;  // disable escaping
+  WINHTTP_FLAG_ESCAPE_DISABLE_QUERY  = $00000080;  // if escaping enabled escape path part, but do not escape query
+
+  // flags for WinHttpSendRequest():
+  WINHTTP_NO_ADDITIONAL_HEADERS   = nil;
+  WINHTTP_NO_REQUEST_DATA         = nil;
+
+  // WinHttpAddRequestHeaders() dwModifiers
+  WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF;
+  WINHTTP_ADDREQ_FLAGS_MASK = $FFFF0000;
+
+  WINHTTP_ADDREQ_FLAG_ADD_IF_NEW                = $10000000;
+  WINHTTP_ADDREQ_FLAG_ADD                       = $20000000;
+  WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA       = $40000000;
+  WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON   = $01000000;
+  WINHTTP_ADDREQ_FLAG_COALESCE                  = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
+  WINHTTP_ADDREQ_FLAG_REPLACE                   = $80000000;
+
+  // URL functions
+  ICU_NO_ENCODE          = $20000000;  // Don't convert unsafe characters to escape sequence
+  ICU_DECODE             = $10000000;  // Convert %XX escape sequences to characters
+  ICU_NO_META            = $08000000;  // Don't convert .. etc. meta path sequences
+  ICU_ENCODE_SPACES_ONLY = $04000000;  // Encode spaces only
+  ICU_BROWSER_MODE       = $02000000;  // Special encode/decode rules for browser
+  ICU_ENCODE_PERCENT     = $00001000;  // Encode any percent (ASCII25)
+
+  ICU_ESCAPE             = $80000000;  // (un)escape URL characters
+  ICU_ESCAPE_AUTHORITY   = $00002000;  // causes InternetCreateUrlA to escape chars in authority components (user, pwd, host)
+  ICU_REJECT_USERPWD     = $00004000;  // rejects usrls whick have username/pwd sections
+
+  INTERNET_SCHEME_HTTP  = INTERNET_SCHEME(1);
+  INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2);
+
+const
+  WINHTTP_ERROR_BASE                      = 12000;
+  ERROR_WINHTTP_OUT_OF_HANDLES            = WINHTTP_ERROR_BASE + 1;
+  ERROR_WINHTTP_TIMEOUT                   = WINHTTP_ERROR_BASE + 2;
+  ERROR_WINHTTP_INTERNAL_ERROR            = WINHTTP_ERROR_BASE + 4;
+  ERROR_WINHTTP_INVALID_URL               = WINHTTP_ERROR_BASE + 5;
+  ERROR_WINHTTP_UNRECOGNIZED_SCHEME       = WINHTTP_ERROR_BASE + 6;
+  ERROR_WINHTTP_NAME_NOT_RESOLVED         = WINHTTP_ERROR_BASE + 7;
+  ERROR_WINHTTP_INVALID_OPTION            = WINHTTP_ERROR_BASE + 9;
+  ERROR_WINHTTP_OPTION_NOT_SETTABLE       = WINHTTP_ERROR_BASE + 11;
+  ERROR_WINHTTP_SHUTDOWN                  = WINHTTP_ERROR_BASE + 12;
+  ERROR_WINHTTP_LOGIN_FAILURE             = WINHTTP_ERROR_BASE + 15;
+  ERROR_WINHTTP_OPERATION_CANCELLED       = WINHTTP_ERROR_BASE + 17;
+  ERROR_WINHTTP_INCORRECT_HANDLE_TYPE     = WINHTTP_ERROR_BASE + 18;
+  ERROR_WINHTTP_INCORRECT_HANDLE_STATE    = WINHTTP_ERROR_BASE + 19;
+  ERROR_WINHTTP_CANNOT_CONNECT            = WINHTTP_ERROR_BASE + 29;
+  ERROR_WINHTTP_CONNECTION_ERROR          = WINHTTP_ERROR_BASE + 30;
+  ERROR_WINHTTP_RESEND_REQUEST            = WINHTTP_ERROR_BASE + 32;
+  ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED   = WINHTTP_ERROR_BASE + 44;
+  ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN	  = WINHTTP_ERROR_BASE + 100;
+  ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND	  = WINHTTP_ERROR_BASE + 101;
+  ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND	  = WINHTTP_ERROR_BASE + 102;
+  ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN	  = WINHTTP_ERROR_BASE + 103;
+  ERROR_WINHTTP_HEADER_NOT_FOUND          = WINHTTP_ERROR_BASE + 150;
+  ERROR_WINHTTP_INVALID_SERVER_RESPONSE   = WINHTTP_ERROR_BASE + 152;
+  ERROR_WINHTTP_INVALID_HEADER            = WINHTTP_ERROR_BASE + 153;
+  ERROR_WINHTTP_INVALID_QUERY_REQUEST     = WINHTTP_ERROR_BASE + 154;
+  ERROR_WINHTTP_HEADER_ALREADY_EXISTS     = WINHTTP_ERROR_BASE + 155;
+  ERROR_WINHTTP_REDIRECT_FAILED           = WINHTTP_ERROR_BASE + 156;
+  ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR  = WINHTTP_ERROR_BASE + 178;
+  ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT     = WINHTTP_ERROR_BASE + 166;
+  ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167;
+  ERROR_WINHTTP_NOT_INITIALIZED           = WINHTTP_ERROR_BASE + 172;
+  ERROR_WINHTTP_SECURE_FAILURE            = WINHTTP_ERROR_BASE + 175;
+
+  // Certificate security errors. Additional information is provided
+  // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification.
+  ERROR_WINHTTP_SECURE_CERT_DATE_INVALID    = WINHTTP_ERROR_BASE + 37;
+  ERROR_WINHTTP_SECURE_CERT_CN_INVALID      = WINHTTP_ERROR_BASE + 38;
+  ERROR_WINHTTP_SECURE_INVALID_CA           = WINHTTP_ERROR_BASE + 45;
+  ERROR_WINHTTP_SECURE_CERT_REV_FAILED      = WINHTTP_ERROR_BASE + 57;
+  ERROR_WINHTTP_SECURE_CHANNEL_ERROR        = WINHTTP_ERROR_BASE + 157;
+  ERROR_WINHTTP_SECURE_INVALID_CERT         = WINHTTP_ERROR_BASE + 169;
+  ERROR_WINHTTP_SECURE_CERT_REVOKED         = WINHTTP_ERROR_BASE + 170;
+  ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE     = WINHTTP_ERROR_BASE + 179;
+
+  ERROR_WINHTTP_AUTODETECTION_FAILED                  = WINHTTP_ERROR_BASE + 180;
+  ERROR_WINHTTP_HEADER_COUNT_EXCEEDED                 = WINHTTP_ERROR_BASE + 181;
+  ERROR_WINHTTP_HEADER_SIZE_OVERFLOW                  = WINHTTP_ERROR_BASE + 182;
+  ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183;
+  ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW               = WINHTTP_ERROR_BASE + 184;
+  ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY            = WINHTTP_ERROR_BASE + 185;
+  ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY     = WINHTTP_ERROR_BASE + 186;
+
+
+const
+  WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE
+                         or WINHTTP_FLAG_BYPASS_PROXY_CACHE
+                         or WINHTTP_FLAG_ESCAPE_DISABLE;
+
+
+type
+  IWinHTTPRequest = interface
+    ['{35C6D9D4-FDCE-42C6-B84C-9294E6FB904C}']
+    function  Handle : HINTERNET;
+    function  AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
+    function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
+    function  SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
+    function  WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
+    function  FlushAndReceiveResponse : Boolean;
+    function  ReadData( const dwRead : DWORD) : TBytes;  overload;
+    function  ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;  overload;
+  end;
+
+  IWinHTTPConnection = interface
+    ['{1C4F78B5-1525-4788-B638-A0E41BCF4D43}']
+    function  Handle : HINTERNET;
+    function  OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
+  end;
+
+  IWinHTTPSession = interface
+    ['{B6F8BD98-0605-4A9E-B671-4CB191D74A5E}']
+    function  Handle : HINTERNET;
+    function  Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
+    function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
+  end;
+
+  IWinHTTPUrl = interface
+    ['{78BE977C-4171-4AF5-A250-FD2890205E63}']
+    // url parts getter
+    function  GetScheme : UnicodeString;
+    function  GetNumScheme : INTERNET_SCHEME;
+    function  GetHostName  : UnicodeString;
+    function  GetPort : INTERNET_PORT;
+    function  GetUserName  : UnicodeString;
+    function  GetPassword  : UnicodeString;
+    function  GetUrlPath   : UnicodeString;
+    function  GetExtraInfo : UnicodeString;
+
+    // url parts setter
+    procedure SetScheme( const value : UnicodeString);
+    procedure SetHostName ( const value : UnicodeString);
+    procedure SetPort( const value : INTERNET_PORT);
+    procedure SetUserName( const value : UnicodeString);
+    procedure SetPassword( const value : UnicodeString);
+    procedure SetUrlPath( const value : UnicodeString);
+    procedure SetExtraInfo( const value : UnicodeString);
+
+    // url as a whole
+    function  BuildUrl : UnicodeString;
+    procedure CrackUrl( const value : UnicodeString);
+
+    // url parts
+    property  Scheme    : UnicodeString   read GetScheme    write SetScheme;
+    property  NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly
+    property  HostName  : UnicodeString   read GetHostName  write SetHostName;
+    property  Port      : INTERNET_PORT   read GetPort      write SetPort;
+    property  UserName  : UnicodeString   read GetUserName  write SetUserName;
+    property  Password  : UnicodeString   read GetPassword  write SetPassword;
+    property  UrlPath   : UnicodeString   read GetUrlPath   write SetUrlPath;
+    property  ExtraInfo : UnicodeString   read GetExtraInfo write SetExtraInfo;
+
+    // url as a whole
+    property  CompleteURL : UnicodeString read BuildUrl write CrackUrl;
+  end;
+
+
+
+
+type
+  TWinHTTPHandleObjectImpl = class( TInterfacedObject)
+  strict protected
+    FHandle : HINTERNET;
+    function  Handle : HINTERNET;
+  public
+    constructor Create( const aHandle : HINTERNET);
+    destructor Destroy;  override;
+  end;
+
+
+  TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession)
+  strict protected
+
+    // IWinHTTPSession
+    function  Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
+    function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
+
+  public
+    constructor Create( const aAgent : UnicodeString;
+                        const aAccessType : DWORD          = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
+                        const aProxy : UnicodeString       = '';
+                        const aProxyBypass : UnicodeString = '';
+                        const aFlags : DWORD               = 0);
+    destructor Destroy;  override;
+  end;
+
+
+  TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection)
+  strict protected
+    FSession : IWinHTTPSession;
+
+    // IWinHTTPConnection
+    function  OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
+
+  public
+    constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
+    destructor Destroy;  override;
+  end;
+
+
+  TAcceptTypesArray = array of string;
+
+  TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest)
+  strict protected
+    FConnection : IWinHTTPConnection;
+
+    // IWinHTTPRequest
+    function  AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
+    function  SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
+    function  SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
+    function  WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
+    function  FlushAndReceiveResponse : Boolean;
+    function  ReadData( const dwRead : DWORD) : TBytes;  overload;
+    function  ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;  overload;
+
+  public
+    constructor Create( const aConnection : IWinHTTPConnection;
+                        const aVerb, aObjName : UnicodeString;
+                        const aVersion : UnicodeString = '';
+                        const aReferrer : UnicodeString = '';
+                        const aAcceptTypes : UnicodeString = '*/*';
+                        const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS
+                        );
+
+    destructor Destroy;  override;
+  end;
+
+
+  TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl)
+  strict private
+    FScheme    : UnicodeString;
+    FNumScheme : INTERNET_SCHEME;
+    FHostName  : UnicodeString;
+    FPort      : INTERNET_PORT;
+    FUserName  : UnicodeString;
+    FPassword  : UnicodeString;
+    FUrlPath   : UnicodeString;
+    FExtraInfo : UnicodeString;
+
+  strict protected
+    // url parts getter
+    function  GetScheme    : UnicodeString;
+    function  GetNumScheme : INTERNET_SCHEME;
+    function  GetHostName  : UnicodeString;
+    function  GetPort      : INTERNET_PORT;
+    function  GetUserName  : UnicodeString;
+    function  GetPassword  : UnicodeString;
+    function  GetUrlPath   : UnicodeString;
+    function  GetExtraInfo : UnicodeString;
+
+    // url parts setter
+    procedure SetScheme(    const value : UnicodeString);
+    procedure SetHostName ( const value : UnicodeString);
+    procedure SetPort(      const value : INTERNET_PORT);
+    procedure SetUserName(  const value : UnicodeString);
+    procedure SetPassword(  const value : UnicodeString);
+    procedure SetUrlPath(   const value : UnicodeString);
+    procedure SetExtraInfo( const value : UnicodeString);
+
+    // url as a whole
+    function  BuildUrl : UnicodeString;
+    procedure CrackUrl( const value : UnicodeString);
+
+  public
+    constructor Create( const aUri : UnicodeString);
+    destructor Destroy;  override;
+  end;
+
+
+  EWinHTTPException = class(Exception);
+
+implementation
+
+const WINHTTP_DLL = 'WinHTTP.dll';
+
+function WinHttpCloseHandle;  stdcall; external WINHTTP_DLL;
+function WinHttpOpen;  stdcall; external WINHTTP_DLL;
+function WinHttpConnect;  stdcall; external WINHTTP_DLL;
+function WinHttpOpenRequest; stdcall; external WINHTTP_DLL;
+function WinHttpSendRequest; stdcall; external WINHTTP_DLL;
+function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL;
+function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL;
+function WinHttpWriteData; stdcall; external WINHTTP_DLL;
+function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL;
+function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL;
+function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL;
+function WinHttpReadData; stdcall; external WINHTTP_DLL;
+function WinHttpCrackUrl; stdcall; external WINHTTP_DLL;
+function WinHttpCreateUrl; stdcall; external WINHTTP_DLL;
+
+
+{ TWinHTTPHandleObjectImpl }
+
+constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET);
+begin
+  inherited Create;
+  FHandle := aHandle;
+
+  if FHandle = nil
+  then raise EWinHTTPException.Create('Invalid handle');
+end;
+
+
+destructor TWinHTTPHandleObjectImpl.Destroy;
+begin
+  try
+    if Assigned(FHandle) then begin
+      WinHttpCloseHandle(FHandle);
+      FHandle := nil;
+    end;
+
+  finally
+    inherited Destroy;
+  end;
+end;
+
+
+function TWinHTTPHandleObjectImpl.Handle : HINTERNET;
+begin
+  result := FHandle;
+end;
+
+
+{ TWinHTTPSessionImpl }
+
+
+constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD;
+                                        const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD);
+var handle : HINTERNET;
+begin
+  handle := WinHttpOpen( PWideChar(aAgent), aAccessType,
+                         PWideChar(Pointer(aProxy)),        // may be nil
+                         PWideChar(Pointer(aProxyBypass)),  // may be nil
+                         aFlags);
+  inherited Create( handle);
+end;
+
+
+destructor TWinHTTPSessionImpl.Destroy;
+begin
+  inherited Destroy;
+  // add code here
+end;
+
+
+function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection;
+begin
+  result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort);
+end;
+
+
+function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
+begin
+  result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
+end;
+
+
+{ TWinHTTPConnectionImpl }
+
+constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
+var handle : HINTERNET;
+begin
+  FSession := aSession;
+  handle   := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0);
+  inherited Create( handle);
+end;
+
+
+destructor TWinHTTPConnectionImpl.Destroy;
+begin
+  inherited Destroy;
+  FSession := nil;
+end;
+
+
+function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
+var dwFlags : DWORD;
+begin
+  dwFlags := WINHTTP_THRIFT_DEFAULTS;
+  if secure
+  then dwFlags := dwFlags or WINHTTP_FLAG_SECURE
+  else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE;
+
+  result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags);
+end;
+
+
+{ TWinHTTPRequestImpl }
+
+constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection;
+                                        const aVerb, aObjName, aVersion, aReferrer : UnicodeString;
+                                        const aAcceptTypes : UnicodeString;
+                                        const aFlags : DWORD
+                                        );
+var handle : HINTERNET;
+    accept : array[0..1] of PWideChar;
+begin
+  FConnection := aConnection;
+
+  accept[0] := PWideChar(aAcceptTypes);
+  accept[1] := nil;
+
+  handle      := WinHttpOpenRequest( FConnection.Handle,
+                                     PWideChar(UpperCase(aVerb)),
+                                     PWideChar(aObjName),
+                                     PWideChar(aVersion),
+                                     PWideChar(aReferrer),
+                                     @accept,
+                                     aFlags);
+  inherited Create( handle);
+end;
+
+
+destructor TWinHTTPRequestImpl.Destroy;
+begin
+  inherited Destroy;
+  FConnection := nil;
+end;
+
+
+function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
+begin
+  result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
+end;
+
+
+function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean;
+begin
+  result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag);
+end;
+
+
+function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean;
+begin
+  result := WinHttpSendRequest( FHandle,
+                                WINHTTP_NO_ADDITIONAL_HEADERS, 0,
+                                pBuf, dwBytes,      // number of bytes in pBuf
+                                dwBytes + dwExtra,  // becomes the Content-Length
+                                nil);               // context for async operations
+end;
+
+
+function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
+begin
+  if not WinHttpWriteData( FHandle, pBuf, dwBytes, result)
+  then result := 0;
+end;
+
+
+function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean;
+begin
+  result := WinHttpReceiveResponse( FHandle, nil);
+end;
+
+
+function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes;
+var dwAvailable, dwReceived : DWORD;
+begin
+  if WinHttpQueryDataAvailable( FHandle, dwAvailable)
+  then dwAvailable := Min( dwRead, dwAvailable)
+  else dwAvailable := 0;
+
+  SetLength( result, dwAvailable);
+  if dwAvailable = 0 then Exit;
+
+  if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived)
+  then SetLength( result, dwReceived)
+  else SetLength( result, 0);
+end;
+
+
+function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;
+var dwAvailable : DWORD;
+begin
+  if WinHttpQueryDataAvailable( FHandle, dwAvailable)
+  then dwAvailable := Min( dwRead, dwAvailable)
+  else dwAvailable := 0;
+
+  if (dwAvailable = 0)
+  or not WinHttpReadData( FHandle, pBuf, dwAvailable, result)
+  then result := 0;
+end;
+
+
+{ TWinHTTPUrlImpl }
+
+constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString);
+begin
+  inherited Create;
+  CrackUrl( aUri)
+end;
+
+
+destructor TWinHTTPUrlImpl.Destroy;
+begin
+  inherited Destroy;
+end;
+
+
+procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString);
+const FLAGS = 0; // no special operations, leave components as-is
+var components : URL_COMPONENTS;
+begin
+  FillChar(components, SizeOf(components), 0);
+  components.dwStructSize := SizeOf(components);
+
+  if value <> '' then begin
+    { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the
+      length member is not zero, both the pointer and length members are returned. }
+    components.dwSchemeLength    := DWORD(-1);
+    components.dwHostNameLength  := DWORD(-1);
+    components.dwUserNameLength  := DWORD(-1);
+    components.dwPasswordLength  := DWORD(-1);
+    components.dwUrlPathLength   := DWORD(-1);
+    components.dwExtraInfoLength := DWORD(-1);
+
+    WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components);
+  end;
+
+  FNumScheme := components.nScheme;
+  FPort      := components.nPort;
+  SetString( FScheme,    components.lpszScheme,    components.dwSchemeLength);
+  SetString( FHostName,  components.lpszHostName,  components.dwHostNameLength);
+  SetString( FUserName,  components.lpszUserName,  components.dwUserNameLength);
+  SetString( FPassword,  components.lpszPassword,  components.dwPasswordLength);
+  SetString( FUrlPath,   components.lpszUrlPath,   components.dwUrlPathLength);
+  SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength);
+end;
+
+
+function TWinHTTPUrlImpl.BuildUrl : UnicodeString;
+const FLAGS = 0; // no special operations, leave components as-is
+var components : URL_COMPONENTS;
+    dwChars : DWORD;
+begin
+  FillChar(components, SizeOf(components), 0);
+  components.dwStructSize      := SizeOf(components);
+  components.lpszScheme        := PWideChar(FScheme);
+  components.dwSchemeLength    := Length(FScheme);
+  components.lpszHostName      := PWideChar(FHostName);
+  components.dwHostNameLength  := Length(FHostName);
+  components.nPort             := FPort;
+  components.lpszUserName      := PWideChar(FUserName);
+  components.dwUserNameLength  := Length(FUserName);
+  components.lpszPassword      := PWideChar(FPassword);
+  components.dwPasswordLength  := Length(FPassword);
+  components.lpszUrlPath       := PWideChar(FUrlPath);
+  components.dwUrlPathLength   := Length(FUrlPath);
+  components.lpszExtraInfo     := PWideChar(FExtraInfo);
+  components.dwExtraInfoLength := Length(FExtraInfo);
+
+  WinHttpCreateUrl( components, FLAGS, nil, dwChars);
+  if dwChars = 0
+  then result := ''
+  else begin
+    SetLength( result, dwChars + 1);
+    WinHttpCreateUrl( components, FLAGS, @result[1], dwChars);
+    SetLength( result, dwChars);  // cut off terminating #0
+  end;
+end;
+
+
+function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString;
+begin
+  result := FExtraInfo;
+end;
+
+function TWinHTTPUrlImpl.GetHostName: UnicodeString;
+begin
+  result := FHostName;
+end;
+
+function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME;
+begin
+  result := FNumScheme;
+end;
+
+function TWinHTTPUrlImpl.GetPassword: UnicodeString;
+begin
+  result := FPassword;
+end;
+
+function TWinHTTPUrlImpl.GetPort: INTERNET_PORT;
+begin
+  result := FPort;
+end;
+
+function TWinHTTPUrlImpl.GetScheme: UnicodeString;
+begin
+  result := FScheme;
+end;
+
+function TWinHTTPUrlImpl.GetUrlPath: UnicodeString;
+begin
+  result := FUrlPath;
+end;
+
+function TWinHTTPUrlImpl.GetUserName: UnicodeString;
+begin
+  result := FUserName;
+end;
+
+procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString);
+begin
+  FExtraInfo := value;
+end;
+
+procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString);
+begin
+  FHostName := value;
+end;
+
+procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString);
+begin
+  FPassword := value;
+end;
+
+procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT);
+begin
+  FPort := value;
+end;
+
+procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString);
+begin
+  FScheme := value;
+end;
+
+procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString);
+begin
+  FUrlPath := value;
+end;
+
+procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString);
+begin
+  FUserName := value;
+end;
+
+
+end.
+
diff --git a/lib/delphi/test/TestClient.pas b/lib/delphi/test/TestClient.pas
index 7b603a3..55bf92b 100644
--- a/lib/delphi/test/TestClient.pas
+++ b/lib/delphi/test/TestClient.pas
@@ -43,6 +43,8 @@
   Thrift.Protocol.JSON,
   Thrift.Protocol,
   Thrift.Transport.Pipes,
+  Thrift.Transport.WinHTTP,
+  Thrift.Transport.MsxmlHTTP,
   Thrift.Transport,
   Thrift.Stream,
   Thrift.Test,
@@ -115,6 +117,7 @@
 
     procedure InitializeProtocolTransportStack;
     procedure ShutdownProtocolTransportStack;
+    function  InitializeHttpTransport( const aTimeoutSetting : Integer) : IHTTPClient;
 
     procedure JSONProtocolReadWriteTest;
     function  PrepareBinaryData( aRandomDist : Boolean; aSize : TTestSize) : TBytes;
@@ -188,7 +191,7 @@
                + '                              instead of host and port'#10
                + '  --named-pipe arg            Windows Named Pipe (e.g. MyThriftPipe)'#10
                + '  --anon-pipes hRead hWrite   Windows Anonymous Pipes pair (handles)'#10
-               + '  --transport arg (=sockets)  Transport: buffered, framed, http, evhttp'#10
+               + '  --transport arg (=sockets)  Transport: buffered, framed, http, winhttp'#10
                + '  --protocol arg (=binary)    Protocol: binary, compact, json'#10
                + '  --ssl                       Encrypted Transport using SSL'#10
                + '  -n [ --testloops ] arg (=1) Number of Tests'#10
@@ -274,14 +277,15 @@
         Console.WriteLine('Using anonymous pipes ('+IntToStr(Integer(setup.hAnonRead))+' and '+IntToStr(Integer(setup.hAnonWrite))+')');
       end
       else if s = '--transport' then begin
-        // --transport arg (=sockets)  Transport: buffered, framed, http, evhttp
+        // --transport arg (=sockets)  Transport: buffered, framed, http, winhttp, evhttp
         s := args[i];
         Inc( i);
 
         if      s = 'buffered' then Include( setup.layered, trns_Buffered)
         else if s = 'framed'   then Include( setup.layered, trns_Framed)
-        else if s = 'http'     then setup.endpoint := trns_Http
-        else if s = 'evhttp'   then setup.endpoint := trns_EvHttp
+        else if s = 'http'     then setup.endpoint := trns_MsXmlHttp
+        else if s = 'winhttp'  then setup.endpoint := trns_WinHttp
+        else if s = 'evhttp'   then setup.endpoint := trns_EvHttp  // recognized, but not supported
         else InvalidArgs;
       end
       else if s = '--protocol' then begin
@@ -1315,11 +1319,41 @@
 end;
 
 
+function TClientThread.InitializeHttpTransport( const aTimeoutSetting : Integer) : IHTTPClient;
+var sUrl : string;
+begin
+  ASSERT( FSetup.endpoint in [trns_MsxmlHttp, trns_WinHttp]);
+
+  if FSetup.useSSL
+  then sUrl := 'https://'
+  else sUrl := 'http://';
+
+  sUrl := sUrl + FSetup.host;
+
+  case FSetup.port of
+    80  : if FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
+    443 : if not FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
+  else
+    if FSetup.port > 0 then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
+  end;
+
+  Console.WriteLine('Target URL: '+sUrl);
+  case FSetup.endpoint of
+    trns_MsxmlHttp :  result := TMsxmlHTTPClientImpl.Create( sUrl);
+    trns_WinHttp   :  result := TWinHTTPClientImpl.Create( sUrl);
+  else
+    raise Exception.Create(ENDPOINT_TRANSPORTS[FSetup.endpoint]+' unhandled case');
+  end;
+
+  result.DnsResolveTimeout := aTimeoutSetting;
+  result.ConnectionTimeout := aTimeoutSetting;
+  result.SendTimeout       := aTimeoutSetting;
+  result.ReadTimeout       := aTimeoutSetting;
+end;
+
+
 procedure TClientThread.InitializeProtocolTransportStack;
-var
-  streamtrans : IStreamTransport;
-  http : IHTTPClient;
-  sUrl : string;
+var streamtrans : IStreamTransport;
 const
   DEBUG_TIMEOUT   = 30 * 1000;
   RELEASE_TIMEOUT = DEFAULT_THRIFT_TIMEOUT;
@@ -1336,24 +1370,10 @@
       FTransport := streamtrans;
     end;
 
-    trns_Http: begin
+    trns_MsxmlHttp,
+    trns_WinHttp: begin
       Console.WriteLine('Using HTTPClient');
-      if FSetup.useSSL
-      then sUrl := 'https://'
-      else sUrl := 'http://';
-      sUrl := sUrl + FSetup.host;
-      case FSetup.port of
-        80  : if FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
-        443 : if not FSetup.useSSL then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
-      else
-        if FSetup.port > 0 then sUrl := sUrl + ':'+ IntToStr(FSetup.port);
-      end;
-      http := THTTPClientImpl.Create( sUrl);
-      http.DnsResolveTimeout := HTTP_TIMEOUTS;
-      http.ConnectionTimeout := HTTP_TIMEOUTS;
-      http.SendTimeout       := HTTP_TIMEOUTS;
-      http.ReadTimeout       := HTTP_TIMEOUTS;
-      FTransport := http;
+      FTransport := InitializeHttpTransport( HTTP_TIMEOUTS);
     end;
 
     trns_EvHttp: begin
diff --git a/lib/delphi/test/TestConstants.pas b/lib/delphi/test/TestConstants.pas
index 37969dc..6bb20e9 100644
--- a/lib/delphi/test/TestConstants.pas
+++ b/lib/delphi/test/TestConstants.pas
@@ -39,7 +39,8 @@
 
   TEndpointTransport = (
     trns_Sockets,
-    trns_Http,
+    trns_MsxmlHttp,
+    trns_WinHttp,
     trns_NamedPipes,
     trns_AnonPipes,
     trns_EvHttp  // as listed on http://thrift.apache.org/test
@@ -63,7 +64,7 @@
                   = ('Buffered', 'Framed');
 
   ENDPOINT_TRANSPORTS : array[TEndpointTransport] of string
-                  = ('Sockets', 'Http', 'Named Pipes','Anon Pipes', 'EvHttp');
+                  = ('Sockets', 'Http', 'WinHttp', 'Named Pipes','Anon Pipes', 'EvHttp');
 
   // defaults are: read=false, write=true
   BINARY_STRICT_READ  = FALSE;
diff --git a/lib/delphi/test/TestServer.pas b/lib/delphi/test/TestServer.pas
index 69cb175..374472c 100644
--- a/lib/delphi/test/TestServer.pas
+++ b/lib/delphi/test/TestServer.pas
@@ -592,7 +592,8 @@
 
         if      s = 'buffered' then Include( layered, trns_Buffered)
         else if s = 'framed'   then Include( layered, trns_Framed)
-        else if s = 'http'     then endpoint := trns_Http
+        else if s = 'http'     then endpoint := trns_MsxmlHttp
+        else if s = 'winhttp'  then endpoint := trns_WinHttp
         else if s = 'anonpipe' then endpoint := trns_AnonPipes
         else InvalidArgs;
       end
@@ -650,8 +651,9 @@
         servertrans := TServerSocketImpl.Create( Port, 0, (trns_Buffered in layered));
       end;
 
-      trns_Http : begin
-        raise Exception.Create(ENDPOINT_TRANSPORTS[endpoint]+' server transport not implemented');
+      trns_MsxmlHttp,
+      trns_WinHttp : begin
+        raise Exception.Create('HTTP server transport not implemented');
       end;
 
       trns_NamedPipes : begin
diff --git a/lib/delphi/test/client.dpr b/lib/delphi/test/client.dpr
index 06dbd3d..1d1607d 100644
--- a/lib/delphi/test/client.dpr
+++ b/lib/delphi/test/client.dpr
@@ -31,6 +31,8 @@
   Thrift.Socket in '..\src\Thrift.Socket.pas',
   Thrift.Exception in '..\src\Thrift.Exception.pas',
   Thrift.Transport.Pipes in '..\src\Thrift.Transport.Pipes.pas',
+  Thrift.Transport.WinHTTP in '..\src\Thrift.Transport.WinHTTP.pas',
+  Thrift.Transport.MsxmlHTTP in '..\src\Thrift.Transport.MsxmlHTTP.pas',
   Thrift.Protocol in '..\src\Thrift.Protocol.pas',
   Thrift.Protocol.JSON in '..\src\Thrift.Protocol.JSON.pas',
   Thrift.Protocol.Compact in '..\src\Thrift.Protocol.Compact.pas',
@@ -39,6 +41,7 @@
   Thrift.Server in '..\src\Thrift.Server.pas',
   Thrift.Stream in '..\src\Thrift.Stream.pas',
   Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas',
+  Thrift.WinHTTP in '..\src\Thrift.WinHTTP.pas',
   Thrift.Utils in '..\src\Thrift.Utils.pas';
 
 var
diff --git a/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr b/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr
index 4278d8f..a57e93a 100644
--- a/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr
+++ b/lib/delphi/test/multiplexed/Multiplex.Test.Client.dpr
@@ -36,6 +36,7 @@
   Thrift.Server in '..\..\src\Thrift.Server.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
+  Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas';
 
 var
diff --git a/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr b/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr
index 120462b..81ed3dd 100644
--- a/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr
+++ b/lib/delphi/test/multiplexed/Multiplex.Test.Server.dpr
@@ -36,6 +36,7 @@
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
+  Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas';
 
diff --git a/lib/delphi/test/serializer/TestSerializer.dpr b/lib/delphi/test/serializer/TestSerializer.dpr
index 51e22a4..1f5ae8b 100644
--- a/lib/delphi/test/serializer/TestSerializer.dpr
+++ b/lib/delphi/test/serializer/TestSerializer.dpr
@@ -34,6 +34,7 @@
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
   Thrift.Serializer in '..\..\src\Thrift.Serializer.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas',
+  Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   System_,
   DebugProtoTest,
diff --git a/lib/delphi/test/server.dpr b/lib/delphi/test/server.dpr
index b5e48a6..9731dd4 100644
--- a/lib/delphi/test/server.dpr
+++ b/lib/delphi/test/server.dpr
@@ -40,6 +40,7 @@
   Thrift.Server in '..\src\Thrift.Server.pas',
   Thrift.TypeRegistry in '..\src\Thrift.TypeRegistry.pas',
   Thrift.Utils in '..\src\Thrift.Utils.pas',
+  Thrift.WinHTTP in '..\src\Thrift.WinHTTP.pas',
   Thrift.Stream in '..\src\Thrift.Stream.pas';
 
 var
diff --git a/lib/delphi/test/skip/skiptest_version1.dpr b/lib/delphi/test/skip/skiptest_version1.dpr
index 803d6bd..0bfe96f 100644
--- a/lib/delphi/test/skip/skiptest_version1.dpr
+++ b/lib/delphi/test/skip/skiptest_version1.dpr
@@ -33,6 +33,7 @@
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
+  Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas';
 
diff --git a/lib/delphi/test/skip/skiptest_version2.dpr b/lib/delphi/test/skip/skiptest_version2.dpr
index 633b247..7893748 100644
--- a/lib/delphi/test/skip/skiptest_version2.dpr
+++ b/lib/delphi/test/skip/skiptest_version2.dpr
@@ -33,6 +33,7 @@
   Thrift.Collections in '..\..\src\Thrift.Collections.pas',
   Thrift.Server in '..\..\src\Thrift.Server.pas',
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
+  Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas';
 
diff --git a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
index 18a7c7d..fd5e3dd 100644
--- a/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
+++ b/lib/delphi/test/typeregistry/TestTypeRegistry.dpr
@@ -34,6 +34,7 @@
   Thrift.Utils in '..\..\src\Thrift.Utils.pas',
   Thrift.Serializer in '..\..\src\Thrift.Serializer.pas',
   Thrift.Stream in '..\..\src\Thrift.Stream.pas',
+  Thrift.WinHTTP in '..\..\src\Thrift.WinHTTP.pas',
   Thrift.TypeRegistry in '..\..\src\Thrift.TypeRegistry.pas',
   DebugProtoTest;