Skip to content

Commit 70160e9

Browse files
More refactoring, now depends on vsoft.uri project
1 parent fa85781 commit 70160e9

5 files changed

Lines changed: 199 additions & 66 deletions

File tree

Source/VSoft.HttpClient.WinHttpClient.pas

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ interface
1010
System.Classes,
1111
WinApi.Windows,
1212
VSoft.CancellationToken,
13+
VSoft.URI,
1314
VSoft.HttpClient,
1415
VSoft.WinHttp.Api,
1516
VSoft.HttpClient.Response;
@@ -18,8 +19,9 @@ interface
1819
type
1920
THttpClient = class(TInterfacedObject, IHttpClient, IHttpClientInternal)
2021
private
22+
FUri : IUri;
23+
2124
FSession : HINTERNET;
22-
FBaseUri : string;
2325
FUserAgent : string;
2426
FRequests : TList<TRequest>;
2527
FAuthTyp : THttpAuthType;
@@ -64,6 +66,7 @@ THttpClient = class(TInterfacedObject, IHttpClient, IHttpClientInternal)
6466
procedure SetBaseUri(const value : string);
6567
function GetUserAgent : string;
6668
procedure SetUserAgent(const value : string);
69+
function GetUri : IUri;
6770

6871
procedure SetAuthType(const value : THttpAuthType);
6972
function GetAuthType : THttpAuthType;
@@ -76,7 +79,9 @@ THttpClient = class(TInterfacedObject, IHttpClient, IHttpClientInternal)
7679
procedure SetUseHttp2(const value : boolean);
7780

7881

79-
function CreateRequest(const resource : string) : TRequest;
82+
function CreateRequest(const resource : string) : TRequest;overload;
83+
function CreateRequest(const uri : IUri) : TRequest;overload;
84+
8085

8186
procedure UseSerializer(const useFunc : TUseSerializerFunc);overload;
8287
procedure UseSerializer(const serializer : IRestSerializer);overload;
@@ -91,7 +96,7 @@ THttpClient = class(TInterfacedObject, IHttpClient, IHttpClientInternal)
9196

9297

9398
public
94-
constructor Create(const baseUri : string);
99+
constructor Create(const uri : IUri);
95100
destructor Destroy;override;
96101
end;
97102

@@ -123,10 +128,20 @@ procedure _HTTPCallback(hInternet: HINTERNET; dwContext: Pointer; dwInternetStat
123128

124129
function THttpClient.CreateRequest(const resource: string): TRequest;
125130
begin
126-
result := TRequest.Create(Self, resource);
131+
if resource = '' then
132+
result := TRequest.Create(Self, FUri)
133+
else
134+
result := TRequest.Create(Self, resource);
127135
FRequests.Add(result); //track requests to ensure they get freed.
128136
end;
129137

138+
function THttpClient.CreateRequest(const uri: IUri): TRequest;
139+
begin
140+
result := TRequest.Create(Self, uri);
141+
FRequests.Add(result); //track requests to ensure they get freed.
142+
143+
end;
144+
130145

131146
{ THttpClient }
132147

@@ -178,15 +193,16 @@ function THttpClient.ConfigureWinHttpRequest(hRequest: HINTERNET; const request:
178193
end;
179194
end;
180195

181-
constructor THttpClient.Create(const baseUri : string);
196+
constructor THttpClient.Create(const uri : IUri);
182197
begin
183198
FRequests := TList<TRequest>.Create;
184-
FBaseUri := baseUri;
199+
FUri := uri;
185200
FUserAgent := 'VSoft.HttpClient';
186201
FWaitEvent := TEvent.Create(nil,false, false,'');
187202
end;
188203

189204

205+
190206
destructor THttpClient.Destroy;
191207
var
192208
i : integer;
@@ -226,7 +242,7 @@ function THttpClient.GetAuthType: THttpAuthType;
226242

227243
function THttpClient.GetBaseUri: string;
228244
begin
229-
result := FBaseUri;
245+
result := FUri.BaseUriString;
230246
end;
231247

232248

@@ -264,6 +280,11 @@ function THttpClient.GetResourceFromRequest(const request: TRequest): string;
264280
end;
265281
end;
266282

283+
function THttpClient.GetUri: IUri;
284+
begin
285+
result := FUri;
286+
end;
287+
267288
function THttpClient.GetUseHttp2: boolean;
268289
begin
269290
result := FUseHttp2;
@@ -631,7 +652,7 @@ function THttpClient.Send(const request: TRequest; const cancellationToken: ICan
631652
urlComp.dwUrlPathLength := DWORD(-1);
632653
urlComp.dwExtraInfoLength := DWORD(-1);
633654

634-
if not WinHttpCrackUrl(PWideChar(FBaseUri), 0, 0, urlComp ) then
655+
if not WinHttpCrackUrl(PWideChar(FUri.BaseUriString), 0, 0, urlComp ) then
635656
begin
636657
FClientError := GetLastError;
637658
raise EHttpClientException.Create(ClientErrorToString(FClientError), FClientError);
@@ -656,7 +677,7 @@ function THttpClient.Send(const request: TRequest; const cancellationToken: ICan
656677
raise EHttpClientException.Create(ClientErrorToString(FClientError), FClientError);
657678
end;
658679

659-
dwOpenRequestFlags := WINHTTP_FLAG_REFRESH;
680+
dwOpenRequestFlags := WINHTTP_FLAG_REFRESH + WINHTTP_FLAG_ESCAPE_PERCENT;
660681
if urlComp.nScheme = INTERNET_SCHEME_HTTPS then
661682
dwOpenRequestFlags := dwOpenRequestFlags + WINHTTP_FLAG_SECURE;
662683

@@ -768,7 +789,7 @@ procedure THttpClient.SetAuthType(const value: THttpAuthType);
768789

769790
procedure THttpClient.SetBaseUri(const value: string);
770791
begin
771-
FBaseUri := value;
792+
FUri.BaseUriString := value;
772793
end;
773794

774795
procedure THttpClient.SetPassword(const value: string);
@@ -842,9 +863,7 @@ function THttpClient.WriteHeaders(hRequest: HINTERNET; const headers: TStrings):
842863
sHeaders := sHeaders + cContentTypeHeader + ': ' +headers.ValueFromIndex[i] + '; charset=' + sCharSet
843864
else
844865
sHeaders := sHeaders + headers.Names[i] + ': ' +headers.ValueFromIndex[i];
845-
846-
// if i < headers.count -1 then
847-
sHeaders := sHeaders + #13#10;
866+
sHeaders := sHeaders + #13#10;
848867
end;
849868

850869
if not WinHttpAddRequestHeaders(hRequest, PWideChar(sHeaders), $ffffffff, WINHTTP_ADDREQ_FLAG_ADD) then

Source/VSoft.HttpClient.pas

Lines changed: 62 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ interface
66
System.Classes,
77
System.SysUtils,
88
System.Typinfo,
9-
VSoft.CancellationToken;
9+
VSoft.CancellationToken,
10+
VSoft.Uri;
1011

1112

1213
type
@@ -68,6 +69,8 @@ TRequest = class;
6869
['{1F09A9A8-A32E-41F3-811B-BA7D5B352185}']
6970
function Send(const request : TRequest; const cancellationToken : ICancellationToken = nil) : IHttpResponse;overload;
7071
procedure ReleaseRequest(const request : TRequest);
72+
function GetBaseUri: string;
73+
function GetUri : IUri;
7174
end;
7275

7376

@@ -79,7 +82,6 @@ TRequest = class
7982
FRequestParams : TStringList;
8083
FFiles : TStringList;
8184
FUrlSegments : TStringList;
82-
FResource : string;
8385
FContent : TStream;
8486
FOwnsContent : boolean;
8587
FSaveAsFile : string;
@@ -90,6 +92,8 @@ TRequest = class
9092
FPassword : string;
9193
FProxyUserName : string;
9294
FProxyPassword : string;
95+
96+
FURI : IUri;
9397
protected
9498
function GetHeaders : TStrings;
9599
function GetParameters : TStrings;
@@ -116,7 +120,8 @@ TRequest = class
116120
function Client : IHttpClientInternal;
117121

118122
public
119-
constructor Create(const client : TObject; const resource : string);
123+
constructor Create(const client : TObject; const resource : string);overload;
124+
constructor Create(const client : TObject; const uri : IUri);overload;
120125
destructor Destroy; override;
121126

122127

@@ -187,7 +192,7 @@ TRequest = class
187192

188193
property FollowRedirects : boolean read FFollowRedirects write FFollowRedirects;
189194
property HtttpMethod : THttpMethod read FHttpMethod;
190-
property Resource : string read FResource write FResource;
195+
property Resource : string read GetResource write SetResource;
191196
property ContentLength : Int64 read GetContentLength;
192197
property SaveAsFile : string read FSaveAsFile write FSaveAsFile;
193198
property UserName : string read FUserName write FUserName;
@@ -224,7 +229,8 @@ TRequest = class
224229
function GetPassword : string;
225230
procedure SetPassword(const value : string);
226231

227-
function CreateRequest(const resource : string) : TRequest;
232+
function CreateRequest(const resource : string) : TRequest;overload;
233+
function CreateRequest(const uri : IUri) : TRequest;overload;
228234

229235
procedure UseSerializer(const useFunc : TUseSerializerFunc);overload;
230236
procedure UseSerializer(const serializer : IRestSerializer);overload;
@@ -240,7 +246,9 @@ TRequest = class
240246
end;
241247

242248
THttpClientFactory = class
243-
class function CreateClient(const baseUri: string = ''): IHttpClient;
249+
class function CreateClient(const uri: string): IHttpClient;overload;
250+
class function CreateClient(const uri: IUri): IHttpClient;overload;
251+
244252
end;
245253

246254
EHttpClientException = class(Exception)
@@ -372,15 +380,46 @@ function TRequest.Client: IHttpClientInternal;
372380
FClient.GetInterface(IHttpClientInternal, result)
373381
end;
374382

375-
constructor TRequest.Create(const client: TObject; const resource: string);
383+
constructor TRequest.Create(const client: TObject; const uri: IUri);
384+
var
385+
queryParam : TQueryParam;
376386
begin
377387
FClient := client;
378-
FResource := resource;
388+
FURI := uri;
379389
FFiles := TStringlist.Create;
380390
FHeaders := TStringList.Create;
381391
FRequestParams := TStringList.Create;
382392
FUrlSegments := TStringList.Create;
383393
FFollowRedirects := true;
394+
395+
if Length(uri.QueryParams) > 0 then
396+
begin
397+
for queryParam in uri.QueryParams do
398+
WithParameter(queryParam.Name, queryParam.Value);
399+
end;
400+
end;
401+
402+
constructor TRequest.Create(const client: TObject; const resource: string);
403+
var
404+
uri : IUri;
405+
error : string;
406+
clientInf : IHttpClientInternal;
407+
sBaseUri : string;
408+
begin
409+
if not client.GetInterface(IHttpClientInternal, clientInf) then
410+
raise Exception.Create('Client does not implement interface!');
411+
sBaseUri := clientInf.GetBaseUri;
412+
413+
if sBaseUri <> '' then
414+
sBaseUri := sBaseUri + '/' + resource
415+
else
416+
sBaseUri := resource;
417+
418+
if not TUriFactory.TryParseWithError(sBaseUri, true, uri, error) then
419+
raise EArgumentException.Create('Invalid Uri : ' + error);
420+
421+
Create(client, uri);
422+
384423
end;
385424

386425
function TRequest.Delete(const cancellationToken: ICancellationToken): IHttpResponse;
@@ -553,7 +592,7 @@ function TRequest.GetParameters: TStrings;
553592

554593
function TRequest.GetResource: string;
555594
begin
556-
result := FResource;
595+
result := FURI.AbsolutePath;
557596
end;
558597

559598
function TRequest.GetUrlSegments: TStrings;
@@ -695,7 +734,7 @@ procedure TRequest.SetContentType(const value: string);
695734

696735
procedure TRequest.SetResource(const value: string);
697736
begin
698-
FResource := value;
737+
FURI.Path := value;
699738
end;
700739

701740

@@ -812,9 +851,20 @@ function TRequest.AddUrlSegement(const name, value: string): TRequest;
812851

813852
{ THttpClientFactory }
814853

815-
class function THttpClientFactory.CreateClient( const baseUri: string): IHttpClient;
854+
class function THttpClientFactory.CreateClient(const uri : string): IHttpClient;
855+
var
856+
theUri : IUri;
857+
error : string;
858+
begin
859+
if not TUriFactory.TryParseWithError(uri, true, theUri, error) then
860+
raise EArgumentOutOfRangeException.Create('Invalid Uri : ' + error );
861+
862+
result := THttpClient.Create(theUri);
863+
end;
864+
865+
class function THttpClientFactory.CreateClient(const uri: IUri): IHttpClient;
816866
begin
817-
result := THttpClient.Create(baseUri);
867+
result := THttpClient.Create(uri);
818868
end;
819869

820870
{ EHttpClientException }

0 commit comments

Comments
 (0)