Skip to content

Commit 77a4a59

Browse files
committed
Support for Indy components
1 parent f5b18dd commit 77a4a59

File tree

5 files changed

+173
-2
lines changed

5 files changed

+173
-2
lines changed

Dist/OpenApiIndy.pas

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
unit OpenApiIndy;
2+
3+
interface
4+
5+
uses
6+
SysUtils, Classes, OpenApiRest, IdHTTP;
7+
8+
type
9+
TIndyHTTP = class(TIdHTTP)
10+
end;
11+
12+
TClientCreatedEvent = procedure(Client: TIdHttp) of object;
13+
14+
TIndyRestRequest = class(TRestRequest)
15+
strict private
16+
FOnClientCreated: TClientCreatedEvent;
17+
public
18+
constructor Create(AOnClientCreated: TClientCreatedEvent);
19+
function Execute: IRestResponse; override;
20+
end;
21+
22+
TIndyRestResponse = class(TInterfacedObject, IRestResponse)
23+
strict private
24+
FClient: TIndyHTTP;
25+
FResponseBody: TBytes;
26+
public
27+
constructor Create(Client: TIndyHTTP; const ResponseBody: TBytes);
28+
destructor Destroy; override;
29+
function StatusCode: Integer;
30+
function ContentAsString: string;
31+
function ContentAsBytes: TBytes;
32+
function GetHeader(const Name: string): string;
33+
end;
34+
35+
TIndyRestRequestFactory = class(TInterfacedObject, IRestRequestFactory)
36+
private
37+
FOnClientCreated: TClientCreatedEvent;
38+
public
39+
function CreateRequest: IRestRequest;
40+
property OnClientCreated: TClientCreatedEvent read FOnClientCreated write FOnClientCreated;
41+
end;
42+
43+
implementation
44+
45+
{ TIndyRestRequestFactory }
46+
47+
function TIndyRestRequestFactory.CreateRequest: IRestRequest;
48+
begin
49+
Result := TIndyRestRequest.Create(FOnClientCreated);
50+
end;
51+
52+
{ TIndyRestRequest }
53+
54+
constructor TIndyRestRequest.Create(AOnClientCreated: TClientCreatedEvent);
55+
begin
56+
inherited Create;
57+
FOnClientCreated := AOnClientCreated;
58+
end;
59+
60+
function TIndyRestRequest.Execute: IRestResponse;
61+
var
62+
Client: TIndyHTTP;
63+
I: Integer;
64+
RequestBody: TStringStream;
65+
ResponseBody: TBytesStream;
66+
begin
67+
Client := TIndyHTTP.Create;
68+
try
69+
if Assigned(FOnClientCreated) then
70+
FOnClientCreated(Client);
71+
72+
Client.HTTPOptions := Client.HTTPOptions + [hoNoProtocolErrorException, hoWantProtocolErrorContent];
73+
RequestBody := nil;
74+
if Body <> '' then
75+
RequestBody := TStringStream.Create(Body, TEncoding.UTF8, False);
76+
try
77+
ResponseBody := TBytesStream.Create;
78+
try
79+
Client.Request.Accept := '';
80+
for I := 0 to Headers.Count - 1 do
81+
Client.Request.CustomHeaders.AddValue(Headers.Names[I], Headers.ValueFromIndex[I]);
82+
Client.DoRequest(Self.Method, BuildUrl, RequestBody, ResponseBody, []);
83+
Result := TIndyRestResponse.Create(Client, Copy(ResponseBody.Bytes, 0, ResponseBody.Size));
84+
Client := nil;
85+
finally
86+
ResponseBody.Free;
87+
end;
88+
finally
89+
RequestBody.Free;
90+
end;
91+
finally
92+
Client.Free;
93+
end;
94+
end;
95+
96+
{ TIndyRestResponse }
97+
98+
constructor TIndyRestResponse.Create(Client: TIndyHTTP; const ResponseBody: TBytes);
99+
begin
100+
inherited Create;
101+
FClient := Client;
102+
FResponseBody := ResponseBody;
103+
end;
104+
105+
destructor TIndyRestResponse.Destroy;
106+
begin
107+
FClient.Free;
108+
inherited;
109+
end;
110+
111+
function TIndyRestResponse.GetHeader(const Name: string): string;
112+
begin
113+
Result := FClient.Response.RawHeaders.Values[Name];
114+
end;
115+
116+
function TIndyRestResponse.StatusCode: Integer;
117+
begin
118+
Result := FClient.ResponseCode;
119+
end;
120+
121+
function TIndyRestResponse.ContentAsBytes: TBytes;
122+
begin
123+
Result := FResponseBody;
124+
end;
125+
126+
function TIndyRestResponse.ContentAsString: string;
127+
begin
128+
Result := TEncoding.UTF8.GetString(ContentAsBytes);
129+
end;
130+
131+
end.

Dist/OpenApiSparkle.pas

+1-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ function TSparkleRestResponse.ContentAsBytes: TBytes;
102102

103103
function TSparkleRestResponse.ContentAsString: string;
104104
begin
105-
Result := TEncoding.UTF8.GetString(FResponse.ContentAsBytes);
105+
Result := TEncoding.UTF8.GetString(ContentAsBytes);
106106
end;
107107

108108
end.

README.md

+33-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,39 @@ It will set the `Authorization` HTTP header with the token value prefixed by `Be
103103

104104
### Client compatibility
105105

106-
Current the generated code doesn't require any dependency on 3rd party units, working with a plain Delphi install. The code is currently using `THttpClient` class from unit `System.Net.HttpClient` to perform the HTTP requests, so the client will only compile on Delphi versions that provide such class. An update is planned to support Indy in older Delphi versions.
106+
Current the generated code doesn't require any dependency on 3rd party units, working with a plain Delphi install. The code is currently using `THttpClient` class from unit `System.Net.HttpClient` to perform the HTTP requests, so the client will only compile on Delphi versions that provide such class.
107+
108+
Alternatively, you can force the client to use Indy components to perform HTTP requests. For that, can use the following code snippet.
109+
110+
```delphi
111+
uses {...}, OpenApiRest, OpenApiIndy;
112+
113+
begin
114+
// At the beginning of your application, set the DefaultRequestFactory
115+
DefaultRequestFactory := TIndyRestRequestFactory.Create;
116+
end;
117+
```
118+
119+
You can intercept the moment where a new `TIdHTTP` client is created - in case you want to setup specific properties like proxy or IO handlers. For that you can use a code like this:
120+
121+
```delphi
122+
uses {...}, OpenApiRest, OpenApiIndy, IdHTTP;
123+
124+
procedure TMainDataModule.IndyClientCreated(Client: TIdHTTP);
125+
begin
126+
// Set extra Client properties here
127+
end;
128+
129+
procedure TMainDataModule.DataModuleCreate(Sender: TObject);
130+
var
131+
Factory: TIndyRestRequestFactory;
132+
begin
133+
// At the beginning of your application, set the DefaultRequestFactory
134+
Factory := TIndyRestRequestFactory.Create;
135+
DefaultRequestFactory := Factory;
136+
Factory.OnClientCreated := IndyClientCreated;
137+
end;
138+
```
107139

108140
## Compiling and running tests
109141

Tests/PetStore3/PetStore3Client.pas

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ interface
55
uses
66
SysUtils,
77
OpenApiRest,
8+
OpenApiUtils,
89
PetStore3Json,
910
PetStore3Dtos;
1011

Tests/TestPetStoreClient.pas

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ interface
77

88
type
99
TPetStoreClientTests = class(TTestCase)
10+
public
11+
procedure SetUp; override;
1012
published
1113
procedure CreateAndGetPet;
1214
end;
@@ -87,6 +89,11 @@ procedure TPetStoreClientTests.CreateAndGetPet;
8789
end;
8890
end;
8991

92+
procedure TPetStoreClientTests.SetUp;
93+
begin
94+
inherited;
95+
end;
96+
9097
initialization
9198
RegisterTest(TPetStoreClientTests.Suite);
9299

0 commit comments

Comments
 (0)