[fpc-pascal] Improvement to TFPHTTPClient Class

2016-07-19 Thread African Wild Dog
Hello,

The current version of the TFPHTTPClient (the one shipped with fpc 3.0) is
coupled to the fpc's sockets framework (fcl-net) so we can't utilize other
tcp connection framework (e.g Synapse) to perform HTTP requests using
TFPHTTPClient.

I have made an improvement to the TFPHTTPClient class (unit fphttpclient,
package fcl-web) which consists of decoupling the client from the socket
framework that is used to perform HTTP requests.

My solution is quite simple: i created a new class called
TTCPConnectionAdapter (as the name suggests, i used the Adapter pattern)
and changed the http client class to perform requests using a
TCPConnectionAdapter instance . The connection adapter is passed as a
parameter to the constructor of the TFPHTTPClient class (dependency
injection). So, the TFPHTTPClient is not tied to the a particular socket
framework anymore. If one wants to perform http requests using e.g Synapse,
just implement the appropriate TTCPConnectionAdapter descendant and inject
it into TFPHTTPClient.

The code below shows the TInetAdapter


==

{ TTCPConnectionAdapter }

TTCPConnectionAdapter = class(TStream)
  strict private
FHost: String;
FPort: Word;
procedure ValidateConnection;
  strict protected
procedure DoConnect(const AHost: String; const APort: Word); virtual;
abstract;
function DoRead(var Buffer; Count: Longint): Longint; virtual; abstract;
function DoWrite(const Buffer; Count: Longint): Longint; virtual;
abstract;
function GetConnected: Boolean; virtual; abstract;
  public
procedure Connect(const AHost: String; const APort: Word);
procedure Disconnect; virtual; abstract;
function Read(var Buffer; Count: Longint): Longint; override;
function Seek(Offset: Longint; Origin: Word): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
property Connected: Boolean read GetConnected;
property Host: String read FHost;
property Port: Word read FPort;
  end;

{ TInetConnectionAdapter }

  TInetConnectionAdapter = class(TTCPConnectionAdapter)
  strict private
FSocket: TInetSocket;
procedure FreeSocket;
  strict protected
procedure DoConnect(const AHost: String; const APort: Word); override;
function DoRead(var Buffer; Count: Longint): Longint; override;
function DoWrite(const Buffer; Count: Longint): Longint; override;
function GetConnected: Boolean; override;
  public
destructor Destroy; override;
procedure Disconnect; override;
  end;

  { TFPCustomHTTPClient }

  TFPCustomHTTPClient = Class(TComponent)
  private
..
FTCPConnection: TTCPConnectionAdapter;
  public
Constructor Create(const ATCPConnection: TTCPConnectionAdapter);
  end;

==

Best regards
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Improvement to TFPHTTPClient Class

2016-07-19 Thread Michael Van Canneyt


Hello,

This will not be applied, for 2 reasons:

1. The whole point of TFPHTTPClient is exactly to couple it to sockets
   framework (fcl-net).
   If you want to use synapse, use httpsend. lnet has a similar component
   for the http protocol.

2. I favour the opposite approach. Abstract out the underlying HTTP 
implementation
   at a higher level.

   For this I have introduced FPWebclient, which has 2 implementations:
   TFPHTTPClient and Synapse.

The new google-api and OData apis use FPWebclient.

Michael.

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Hello, I suggest that you change the TFPGMap in fgl.

2016-07-19 Thread Felipe Monteiro de Carvalho
Hello,

You could always send a patch with a TFPGHashedMap or TFPGRedBlackMap
implementation.

thanks,
-- 
Felipe Monteiro de Carvalho
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Improvement to TFPHTTPClient Class

2016-07-19 Thread African Wild Dog
2016-07-19 4:52 GMT-03:00 Michael Van Canneyt :

>
> 1. The whole point of TFPHTTPClient is exactly to couple it to sockets
>framework (fcl-net).
>If you want to use synapse, use httpsend. lnet has a similar component
>for the http protocol.
>
>
I dont want to use synapse. I am developing bindings for a c library. The
library offers TCP connection functionality but does not provide any
support for http. I need to use that library due to some particularities of
my project.

I do not understand the need for such coupling between http client and
fcl-net. It is like coupling SQLDb with a specific RDBMS.


> 2. I favour the opposite approach. Abstract out the underlying HTTP
> implementation
>at a higher level.
>

Why should we duplicate the code? Why should we implement the same
functionality in several diferent places?


>
>For this I have introduced FPWebclient, which has 2 implementations:
>TFPHTTPClient and Synapse.
>
>
Through TAbstractWebClient you are introducing another level of complexity
to do the same task: perform http requests. TAbstractWebClient is actually
an adapter to diferent http implementations. TAbstractWebClient is an
interesting class. However, It is a poor solution, IMHO.

Best regards
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Re: [fpc-pascal] Improvement to TFPHTTPClient Class

2016-07-19 Thread Michael Van Canneyt



On Tue, 19 Jul 2016, African Wild Dog wrote:


2016-07-19 4:52 GMT-03:00 Michael Van Canneyt :



1. The whole point of TFPHTTPClient is exactly to couple it to sockets
   framework (fcl-net).
   If you want to use synapse, use httpsend. lnet has a similar component
   for the http protocol.



I dont want to use synapse. I am developing bindings for a c library. The
library offers TCP connection functionality but does not provide any
support for http. I need to use that library due to some particularities of
my project.

I do not understand the need for such coupling between http client and
fcl-net. It is like coupling SQLDb with a specific RDBMS.


The comparison is at fault, but I will not press the point.


2. I favour the opposite approach. Abstract out the underlying HTTP
implementation
   at a higher level.



Why should we duplicate the code? Why should we implement the same
functionality in several diferent places?


Because all Pascal TCP toolkits out there offer a HTTP Client. (lnet, indy,
synapse). By doing this, I leave the choice up to the user which one to use
for various APIs that are built ON TOP of HTTP.

Your use case is simply one I didn't foresee,
Because I assume that any decent TCP toolkit offers a HTTP client.

However, now that I understand what you actually need, we can consider this 
use-case.

I will accept the patch, on the condition that you provide a binding for a C
TCP/IP library too. If your c library is open source, then we can use that.
if not, then I'd ask you to provide an libevent implementation.

It has no point abstracting out something if we have only 1 implementation.

Michael.
___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal