blob: 6ad840066563dc42903d5e9a668deeeed164123a [file] [log] [blame]
Jens Geyer02230912019-04-03 01:12:51 +02001(*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 *)
19unit Thrift.WinHTTP;
20
21{$I Thrift.Defines.inc}
22{$SCOPEDENUMS ON}
23
24// packing according to winhttp.h
25{$IFDEF Win64} {$ALIGN 8} {$ELSE} {$ALIGN 4} {$ENDIF}
26
27interface
28
29uses
30 Windows,
31 Classes,
32 SysUtils,
33 Math,
34 Generics.Collections;
35
36
37type
38 HINTERNET = type Pointer;
39 INTERNET_PORT = type WORD;
40 INTERNET_SCHEME = type Integer;
41 LPLPCWSTR = ^LPCWSTR;
42
43 LPURL_COMPONENTS = ^URL_COMPONENTS;
44 URL_COMPONENTS = record
45 dwStructSize : DWORD; // set to SizeOf(URL_COMPONENTS)
46 lpszScheme : LPWSTR; // scheme name
47 dwSchemeLength : DWORD;
48 nScheme : INTERNET_SCHEME; // enumerated scheme type
49 lpszHostName : LPWSTR; // host name
50 dwHostNameLength : DWORD;
51 nPort : INTERNET_PORT; // port number
52 lpszUserName : LPWSTR; // user name
53 dwUserNameLength : DWORD;
54 lpszPassword : LPWSTR; // password
55 dwPasswordLength : DWORD;
56 lpszUrlPath : LPWSTR; // URL-path
57 dwUrlPathLength : DWORD;
58 lpszExtraInfo : LPWSTR; // extra information
59 dwExtraInfoLength : DWORD;
60 end;
61
62 URL_COMPONENTSW = URL_COMPONENTS;
63 LPURL_COMPONENTSW = LPURL_COMPONENTS;
64
65
66function WinHttpCloseHandle( aHandle : HINTERNET) : BOOL; stdcall;
67
68function WinHttpOpen( const pszAgentW : LPCWSTR;
69 const dwAccessType : DWORD;
70 const pszProxyW : LPCWSTR;
71 const pszProxyBypassW : LPCWSTR;
72 const dwFlags : DWORD
73 ) : HINTERNET; stdcall;
74
75function WinHttpConnect( const hSession : HINTERNET;
76 const pswzServerName : LPCWSTR;
77 const nServerPort : INTERNET_PORT;
78 const dwReserved : DWORD
79 ) : HINTERNET; stdcall;
80
81function WinHttpOpenRequest( const hConnect : HINTERNET;
82 const pwszVerb, pwszObjectName, pwszVersion, pwszReferrer : LPCWSTR;
83 const ppwszAcceptTypes : LPLPCWSTR;
84 const dwFlags : DWORD
85 ) : HINTERNET; stdcall;
86
87function WinHttpSetTimeouts( const hRequestOrSession : HINTERNET;
88 const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32
89 ) : BOOL; stdcall;
90
91function WinHttpAddRequestHeaders( const hRequest : HINTERNET;
92 const pwszHeaders : LPCWSTR;
93 const dwHeadersLengthInChars : DWORD;
94 const dwModifiers : DWORD
95 ) : BOOL; stdcall;
96
97function WinHttpSendRequest( const hRequest : HINTERNET;
98 const lpszHeaders : LPCWSTR;
99 const dwHeadersLength : DWORD;
100 const lpOptional : Pointer;
101 const dwOptionalLength : DWORD;
102 const dwTotalLength : DWORD;
103 const pContext : Pointer
104 ) : BOOL; stdcall;
105
106function WinHttpWriteData( const hRequest : HINTERNET;
107 const pBuf : Pointer;
108 const dwBytesToWrite : DWORD;
109 out dwBytesWritten : DWORD
110 ) : BOOL; stdcall;
111
112function WinHttpReceiveResponse( const hRequest : HINTERNET; const lpReserved : Pointer) : BOOL; stdcall;
113
114function WinHttpQueryHeaders( const hRequest : HINTERNET;
115 const dwInfoLevel : DWORD;
116 const pwszName : LPCWSTR;
117 const lpBuffer : Pointer;
118 var dwBufferLength : DWORD;
119 var dwIndex : DWORD
120 ) : BOOL; stdcall;
121
122function WinHttpQueryDataAvailable( const hRequest : HINTERNET;
123 var dwNumberOfBytesAvailable : DWORD
124 ) : BOOL; stdcall;
125
126function WinHttpReadData( const hRequest : HINTERNET;
127 const lpBuffer : Pointer;
128 const dwBytesToRead : DWORD;
129 out dwBytesRead : DWORD
130 ) : BOOL; stdcall;
131
132function WinHttpCrackUrl( const pwszUrl : LPCWSTR;
133 const dwUrlLength : DWORD;
134 const dwFlags : DWORD;
135 var urlComponents : URL_COMPONENTS
136 ) : BOOL; stdcall;
137
138function WinHttpCreateUrl( const UrlComponents : URL_COMPONENTS;
139 const dwFlags : DWORD;
140 const pwszUrl : LPCWSTR;
141 var pdwUrlLength : DWORD
142 ) : BOOL; stdcall;
143
144
145const
146 // WinHttpOpen dwAccessType values
147 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0;
148 WINHTTP_ACCESS_TYPE_NO_PROXY = 1;
149 WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3;
150
151 // flags for WinHttpOpen():
152 WINHTTP_FLAG_ASYNC = $10000000; // want async session, requires WinHttpSetStatusCallback() usage
153
154 // ports
155 INTERNET_DEFAULT_PORT = 0; // use the protocol-specific default (80 or 443)
156
157 // flags for WinHttpOpenRequest():
158 WINHTTP_FLAG_SECURE = $00800000; // use SSL if applicable (HTTPS)
159 WINHTTP_FLAG_ESCAPE_PERCENT = $00000004; // if escaping enabled, escape percent as well
160 WINHTTP_FLAG_NULL_CODEPAGE = $00000008; // assume all symbols are ASCII, use fast convertion
161 WINHTTP_FLAG_BYPASS_PROXY_CACHE = $00000100; // add "pragma: no-cache" request header
162 WINHTTP_FLAG_REFRESH = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
163 WINHTTP_FLAG_ESCAPE_DISABLE = $00000040; // disable escaping
164 WINHTTP_FLAG_ESCAPE_DISABLE_QUERY = $00000080; // if escaping enabled escape path part, but do not escape query
165
166 // flags for WinHttpSendRequest():
167 WINHTTP_NO_ADDITIONAL_HEADERS = nil;
168 WINHTTP_NO_REQUEST_DATA = nil;
169
170 // WinHttpAddRequestHeaders() dwModifiers
171 WINHTTP_ADDREQ_INDEX_MASK = $0000FFFF;
172 WINHTTP_ADDREQ_FLAGS_MASK = $FFFF0000;
173
174 WINHTTP_ADDREQ_FLAG_ADD_IF_NEW = $10000000;
175 WINHTTP_ADDREQ_FLAG_ADD = $20000000;
176 WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA = $40000000;
177 WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON = $01000000;
178 WINHTTP_ADDREQ_FLAG_COALESCE = WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA;
179 WINHTTP_ADDREQ_FLAG_REPLACE = $80000000;
180
181 // URL functions
182 ICU_NO_ENCODE = $20000000; // Don't convert unsafe characters to escape sequence
183 ICU_DECODE = $10000000; // Convert %XX escape sequences to characters
184 ICU_NO_META = $08000000; // Don't convert .. etc. meta path sequences
185 ICU_ENCODE_SPACES_ONLY = $04000000; // Encode spaces only
186 ICU_BROWSER_MODE = $02000000; // Special encode/decode rules for browser
187 ICU_ENCODE_PERCENT = $00001000; // Encode any percent (ASCII25)
188
189 ICU_ESCAPE = $80000000; // (un)escape URL characters
190 ICU_ESCAPE_AUTHORITY = $00002000; // causes InternetCreateUrlA to escape chars in authority components (user, pwd, host)
191 ICU_REJECT_USERPWD = $00004000; // rejects usrls whick have username/pwd sections
192
193 INTERNET_SCHEME_HTTP = INTERNET_SCHEME(1);
194 INTERNET_SCHEME_HTTPS = INTERNET_SCHEME(2);
195
196const
197 WINHTTP_ERROR_BASE = 12000;
198 ERROR_WINHTTP_OUT_OF_HANDLES = WINHTTP_ERROR_BASE + 1;
199 ERROR_WINHTTP_TIMEOUT = WINHTTP_ERROR_BASE + 2;
200 ERROR_WINHTTP_INTERNAL_ERROR = WINHTTP_ERROR_BASE + 4;
201 ERROR_WINHTTP_INVALID_URL = WINHTTP_ERROR_BASE + 5;
202 ERROR_WINHTTP_UNRECOGNIZED_SCHEME = WINHTTP_ERROR_BASE + 6;
203 ERROR_WINHTTP_NAME_NOT_RESOLVED = WINHTTP_ERROR_BASE + 7;
204 ERROR_WINHTTP_INVALID_OPTION = WINHTTP_ERROR_BASE + 9;
205 ERROR_WINHTTP_OPTION_NOT_SETTABLE = WINHTTP_ERROR_BASE + 11;
206 ERROR_WINHTTP_SHUTDOWN = WINHTTP_ERROR_BASE + 12;
207 ERROR_WINHTTP_LOGIN_FAILURE = WINHTTP_ERROR_BASE + 15;
208 ERROR_WINHTTP_OPERATION_CANCELLED = WINHTTP_ERROR_BASE + 17;
209 ERROR_WINHTTP_INCORRECT_HANDLE_TYPE = WINHTTP_ERROR_BASE + 18;
210 ERROR_WINHTTP_INCORRECT_HANDLE_STATE = WINHTTP_ERROR_BASE + 19;
211 ERROR_WINHTTP_CANNOT_CONNECT = WINHTTP_ERROR_BASE + 29;
212 ERROR_WINHTTP_CONNECTION_ERROR = WINHTTP_ERROR_BASE + 30;
213 ERROR_WINHTTP_RESEND_REQUEST = WINHTTP_ERROR_BASE + 32;
214 ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = WINHTTP_ERROR_BASE + 44;
215 ERROR_WINHTTP_CANNOT_CALL_BEFORE_OPEN = WINHTTP_ERROR_BASE + 100;
216 ERROR_WINHTTP_CANNOT_CALL_BEFORE_SEND = WINHTTP_ERROR_BASE + 101;
217 ERROR_WINHTTP_CANNOT_CALL_AFTER_SEND = WINHTTP_ERROR_BASE + 102;
218 ERROR_WINHTTP_CANNOT_CALL_AFTER_OPEN = WINHTTP_ERROR_BASE + 103;
219 ERROR_WINHTTP_HEADER_NOT_FOUND = WINHTTP_ERROR_BASE + 150;
220 ERROR_WINHTTP_INVALID_SERVER_RESPONSE = WINHTTP_ERROR_BASE + 152;
221 ERROR_WINHTTP_INVALID_HEADER = WINHTTP_ERROR_BASE + 153;
222 ERROR_WINHTTP_INVALID_QUERY_REQUEST = WINHTTP_ERROR_BASE + 154;
223 ERROR_WINHTTP_HEADER_ALREADY_EXISTS = WINHTTP_ERROR_BASE + 155;
224 ERROR_WINHTTP_REDIRECT_FAILED = WINHTTP_ERROR_BASE + 156;
225 ERROR_WINHTTP_AUTO_PROXY_SERVICE_ERROR = WINHTTP_ERROR_BASE + 178;
226 ERROR_WINHTTP_BAD_AUTO_PROXY_SCRIPT = WINHTTP_ERROR_BASE + 166;
227 ERROR_WINHTTP_UNABLE_TO_DOWNLOAD_SCRIPT = WINHTTP_ERROR_BASE + 167;
228 ERROR_WINHTTP_NOT_INITIALIZED = WINHTTP_ERROR_BASE + 172;
229 ERROR_WINHTTP_SECURE_FAILURE = WINHTTP_ERROR_BASE + 175;
230
231 // Certificate security errors. Additional information is provided
232 // via the WINHTTP_CALLBACK_STATUS_SECURE_FAILURE callback notification.
233 ERROR_WINHTTP_SECURE_CERT_DATE_INVALID = WINHTTP_ERROR_BASE + 37;
234 ERROR_WINHTTP_SECURE_CERT_CN_INVALID = WINHTTP_ERROR_BASE + 38;
235 ERROR_WINHTTP_SECURE_INVALID_CA = WINHTTP_ERROR_BASE + 45;
236 ERROR_WINHTTP_SECURE_CERT_REV_FAILED = WINHTTP_ERROR_BASE + 57;
237 ERROR_WINHTTP_SECURE_CHANNEL_ERROR = WINHTTP_ERROR_BASE + 157;
238 ERROR_WINHTTP_SECURE_INVALID_CERT = WINHTTP_ERROR_BASE + 169;
239 ERROR_WINHTTP_SECURE_CERT_REVOKED = WINHTTP_ERROR_BASE + 170;
240 ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE = WINHTTP_ERROR_BASE + 179;
241
242 ERROR_WINHTTP_AUTODETECTION_FAILED = WINHTTP_ERROR_BASE + 180;
243 ERROR_WINHTTP_HEADER_COUNT_EXCEEDED = WINHTTP_ERROR_BASE + 181;
244 ERROR_WINHTTP_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 182;
245 ERROR_WINHTTP_CHUNKED_ENCODING_HEADER_SIZE_OVERFLOW = WINHTTP_ERROR_BASE + 183;
246 ERROR_WINHTTP_RESPONSE_DRAIN_OVERFLOW = WINHTTP_ERROR_BASE + 184;
247 ERROR_WINHTTP_CLIENT_CERT_NO_PRIVATE_KEY = WINHTTP_ERROR_BASE + 185;
248 ERROR_WINHTTP_CLIENT_CERT_NO_ACCESS_PRIVATE_KEY = WINHTTP_ERROR_BASE + 186;
249
250
251const
252 WINHTTP_THRIFT_DEFAULTS = WINHTTP_FLAG_NULL_CODEPAGE
253 or WINHTTP_FLAG_BYPASS_PROXY_CACHE
254 or WINHTTP_FLAG_ESCAPE_DISABLE;
255
256
257type
258 IWinHTTPRequest = interface
259 ['{35C6D9D4-FDCE-42C6-B84C-9294E6FB904C}']
260 function Handle : HINTERNET;
261 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
262 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
263 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
264 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
265 function FlushAndReceiveResponse : Boolean;
266 function ReadData( const dwRead : DWORD) : TBytes; overload;
267 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
268 end;
269
270 IWinHTTPConnection = interface
271 ['{1C4F78B5-1525-4788-B638-A0E41BCF4D43}']
272 function Handle : HINTERNET;
273 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
274 end;
275
276 IWinHTTPSession = interface
277 ['{B6F8BD98-0605-4A9E-B671-4CB191D74A5E}']
278 function Handle : HINTERNET;
279 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
280 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
281 end;
282
283 IWinHTTPUrl = interface
284 ['{78BE977C-4171-4AF5-A250-FD2890205E63}']
285 // url parts getter
286 function GetScheme : UnicodeString;
287 function GetNumScheme : INTERNET_SCHEME;
288 function GetHostName : UnicodeString;
289 function GetPort : INTERNET_PORT;
290 function GetUserName : UnicodeString;
291 function GetPassword : UnicodeString;
292 function GetUrlPath : UnicodeString;
293 function GetExtraInfo : UnicodeString;
294
295 // url parts setter
296 procedure SetScheme( const value : UnicodeString);
297 procedure SetHostName ( const value : UnicodeString);
298 procedure SetPort( const value : INTERNET_PORT);
299 procedure SetUserName( const value : UnicodeString);
300 procedure SetPassword( const value : UnicodeString);
301 procedure SetUrlPath( const value : UnicodeString);
302 procedure SetExtraInfo( const value : UnicodeString);
303
304 // url as a whole
305 function BuildUrl : UnicodeString;
306 procedure CrackUrl( const value : UnicodeString);
307
308 // url parts
309 property Scheme : UnicodeString read GetScheme write SetScheme;
310 property NumScheme : INTERNET_SCHEME read GetNumScheme; // readonly
311 property HostName : UnicodeString read GetHostName write SetHostName;
312 property Port : INTERNET_PORT read GetPort write SetPort;
313 property UserName : UnicodeString read GetUserName write SetUserName;
314 property Password : UnicodeString read GetPassword write SetPassword;
315 property UrlPath : UnicodeString read GetUrlPath write SetUrlPath;
316 property ExtraInfo : UnicodeString read GetExtraInfo write SetExtraInfo;
317
318 // url as a whole
319 property CompleteURL : UnicodeString read BuildUrl write CrackUrl;
320 end;
321
322
323
324
325type
326 TWinHTTPHandleObjectImpl = class( TInterfacedObject)
327 strict protected
328 FHandle : HINTERNET;
329 function Handle : HINTERNET;
330 public
331 constructor Create( const aHandle : HINTERNET);
332 destructor Destroy; override;
333 end;
334
335
336 TWinHTTPSessionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPSession)
337 strict protected
338
339 // IWinHTTPSession
340 function Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT = INTERNET_DEFAULT_PORT) : IWinHTTPConnection;
341 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
342
343 public
344 constructor Create( const aAgent : UnicodeString;
345 const aAccessType : DWORD = WINHTTP_ACCESS_TYPE_DEFAULT_PROXY;
346 const aProxy : UnicodeString = '';
347 const aProxyBypass : UnicodeString = '';
348 const aFlags : DWORD = 0);
349 destructor Destroy; override;
350 end;
351
352
353 TWinHTTPConnectionImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPConnection)
354 strict protected
355 FSession : IWinHTTPSession;
356
357 // IWinHTTPConnection
358 function OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
359
360 public
361 constructor Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
362 destructor Destroy; override;
363 end;
364
365
366 TAcceptTypesArray = array of string;
367
368 TWinHTTPRequestImpl = class( TWinHTTPHandleObjectImpl, IWinHTTPRequest)
369 strict protected
370 FConnection : IWinHTTPConnection;
371
372 // IWinHTTPRequest
373 function AddRequestHeader( const aHeader : string; const addflag : DWORD = WINHTTP_ADDREQ_FLAG_ADD) : Boolean;
374 function SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
375 function SendRequest( const pBuf : Pointer; const dwBytes : DWORD; const dwExtra : DWORD = 0) : Boolean;
376 function WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
377 function FlushAndReceiveResponse : Boolean;
378 function ReadData( const dwRead : DWORD) : TBytes; overload;
379 function ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD; overload;
380
381 public
382 constructor Create( const aConnection : IWinHTTPConnection;
383 const aVerb, aObjName : UnicodeString;
384 const aVersion : UnicodeString = '';
385 const aReferrer : UnicodeString = '';
386 const aAcceptTypes : UnicodeString = '*/*';
387 const aFlags : DWORD = WINHTTP_THRIFT_DEFAULTS
388 );
389
390 destructor Destroy; override;
391 end;
392
393
394 TWinHTTPUrlImpl = class( TInterfacedObject, IWinHTTPUrl)
395 strict private
396 FScheme : UnicodeString;
397 FNumScheme : INTERNET_SCHEME;
398 FHostName : UnicodeString;
399 FPort : INTERNET_PORT;
400 FUserName : UnicodeString;
401 FPassword : UnicodeString;
402 FUrlPath : UnicodeString;
403 FExtraInfo : UnicodeString;
404
405 strict protected
406 // url parts getter
407 function GetScheme : UnicodeString;
408 function GetNumScheme : INTERNET_SCHEME;
409 function GetHostName : UnicodeString;
410 function GetPort : INTERNET_PORT;
411 function GetUserName : UnicodeString;
412 function GetPassword : UnicodeString;
413 function GetUrlPath : UnicodeString;
414 function GetExtraInfo : UnicodeString;
415
416 // url parts setter
417 procedure SetScheme( const value : UnicodeString);
418 procedure SetHostName ( const value : UnicodeString);
419 procedure SetPort( const value : INTERNET_PORT);
420 procedure SetUserName( const value : UnicodeString);
421 procedure SetPassword( const value : UnicodeString);
422 procedure SetUrlPath( const value : UnicodeString);
423 procedure SetExtraInfo( const value : UnicodeString);
424
425 // url as a whole
426 function BuildUrl : UnicodeString;
427 procedure CrackUrl( const value : UnicodeString);
428
429 public
430 constructor Create( const aUri : UnicodeString);
431 destructor Destroy; override;
432 end;
433
434
435 EWinHTTPException = class(Exception);
436
437implementation
438
439const WINHTTP_DLL = 'WinHTTP.dll';
440
441function WinHttpCloseHandle; stdcall; external WINHTTP_DLL;
442function WinHttpOpen; stdcall; external WINHTTP_DLL;
443function WinHttpConnect; stdcall; external WINHTTP_DLL;
444function WinHttpOpenRequest; stdcall; external WINHTTP_DLL;
445function WinHttpSendRequest; stdcall; external WINHTTP_DLL;
446function WinHttpSetTimeouts; stdcall; external WINHTTP_DLL;
447function WinHttpAddRequestHeaders; stdcall; external WINHTTP_DLL;
448function WinHttpWriteData; stdcall; external WINHTTP_DLL;
449function WinHttpReceiveResponse; stdcall; external WINHTTP_DLL;
450function WinHttpQueryHeaders; stdcall; external WINHTTP_DLL;
451function WinHttpQueryDataAvailable; stdcall; external WINHTTP_DLL;
452function WinHttpReadData; stdcall; external WINHTTP_DLL;
453function WinHttpCrackUrl; stdcall; external WINHTTP_DLL;
454function WinHttpCreateUrl; stdcall; external WINHTTP_DLL;
455
456
457{ TWinHTTPHandleObjectImpl }
458
459constructor TWinHTTPHandleObjectImpl.Create( const aHandle : HINTERNET);
460begin
461 inherited Create;
462 FHandle := aHandle;
463
464 if FHandle = nil
465 then raise EWinHTTPException.Create('Invalid handle');
466end;
467
468
469destructor TWinHTTPHandleObjectImpl.Destroy;
470begin
471 try
472 if Assigned(FHandle) then begin
473 WinHttpCloseHandle(FHandle);
474 FHandle := nil;
475 end;
476
477 finally
478 inherited Destroy;
479 end;
480end;
481
482
483function TWinHTTPHandleObjectImpl.Handle : HINTERNET;
484begin
485 result := FHandle;
486end;
487
488
489{ TWinHTTPSessionImpl }
490
491
492constructor TWinHTTPSessionImpl.Create( const aAgent : UnicodeString; const aAccessType : DWORD;
493 const aProxy, aProxyBypass : UnicodeString; const aFlags : DWORD);
494var handle : HINTERNET;
495begin
496 handle := WinHttpOpen( PWideChar(aAgent), aAccessType,
497 PWideChar(Pointer(aProxy)), // may be nil
498 PWideChar(Pointer(aProxyBypass)), // may be nil
499 aFlags);
Jens Geyer14a9a122019-05-09 23:29:24 +0200500 if handle = nil then RaiseLastOSError;
Jens Geyer02230912019-04-03 01:12:51 +0200501 inherited Create( handle);
502end;
503
504
505destructor TWinHTTPSessionImpl.Destroy;
506begin
507 inherited Destroy;
508 // add code here
509end;
510
511
512function TWinHTTPSessionImpl.Connect( const aHostName : UnicodeString; const aPort : INTERNET_PORT) : IWinHTTPConnection;
513begin
514 result := TWinHTTPConnectionImpl.Create( Self, aHostName, aPort);
515end;
516
517
518function TWinHTTPSessionImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
519begin
520 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
521end;
522
523
524{ TWinHTTPConnectionImpl }
525
526constructor TWinHTTPConnectionImpl.Create( const aSession : IWinHTTPSession; const aHostName : UnicodeString; const aPort : INTERNET_PORT);
527var handle : HINTERNET;
528begin
529 FSession := aSession;
530 handle := WinHttpConnect( FSession.Handle, PWideChar(aHostName), aPort, 0);
Jens Geyer14a9a122019-05-09 23:29:24 +0200531 if handle = nil then RaiseLastOSError;
Jens Geyer02230912019-04-03 01:12:51 +0200532 inherited Create( handle);
533end;
534
535
536destructor TWinHTTPConnectionImpl.Destroy;
537begin
538 inherited Destroy;
539 FSession := nil;
540end;
541
542
543function TWinHTTPConnectionImpl.OpenRequest( const secure : Boolean; const aVerb, aObjName, aAcceptTypes : UnicodeString) : IWinHTTPRequest;
544var dwFlags : DWORD;
545begin
546 dwFlags := WINHTTP_THRIFT_DEFAULTS;
547 if secure
548 then dwFlags := dwFlags or WINHTTP_FLAG_SECURE
549 else dwFlags := dwFlags and not WINHTTP_FLAG_SECURE;
550
551 result := TWinHTTPRequestImpl.Create( Self, aVerb, aObjName, '', '', aAcceptTypes, dwFlags);
552end;
553
554
555{ TWinHTTPRequestImpl }
556
557constructor TWinHTTPRequestImpl.Create( const aConnection : IWinHTTPConnection;
558 const aVerb, aObjName, aVersion, aReferrer : UnicodeString;
559 const aAcceptTypes : UnicodeString;
560 const aFlags : DWORD
561 );
562var handle : HINTERNET;
563 accept : array[0..1] of PWideChar;
564begin
565 FConnection := aConnection;
566
567 accept[0] := PWideChar(aAcceptTypes);
568 accept[1] := nil;
569
570 handle := WinHttpOpenRequest( FConnection.Handle,
571 PWideChar(UpperCase(aVerb)),
572 PWideChar(aObjName),
573 PWideChar(aVersion),
574 PWideChar(aReferrer),
575 @accept,
576 aFlags);
Jens Geyer14a9a122019-05-09 23:29:24 +0200577 if handle = nil then RaiseLastOSError;
Jens Geyer02230912019-04-03 01:12:51 +0200578 inherited Create( handle);
579end;
580
581
582destructor TWinHTTPRequestImpl.Destroy;
583begin
584 inherited Destroy;
585 FConnection := nil;
586end;
587
588
589function TWinHTTPRequestImpl.SetTimeouts( const aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout : Int32) : Boolean;
590begin
591 result := WinHttpSetTimeouts( FHandle, aResolveTimeout, aConnectTimeout, aSendTimeout, aReceiveTimeout);
592end;
593
594
595function TWinHTTPRequestImpl.AddRequestHeader( const aHeader : string; const addflag : DWORD) : Boolean;
596begin
597 result := WinHttpAddRequestHeaders( FHandle, PWideChar(aHeader), DWORD(-1), addflag);
598end;
599
600
601function TWinHTTPRequestImpl.SendRequest( const pBuf : Pointer; const dwBytes, dwExtra : DWORD) : Boolean;
602begin
603 result := WinHttpSendRequest( FHandle,
604 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
605 pBuf, dwBytes, // number of bytes in pBuf
606 dwBytes + dwExtra, // becomes the Content-Length
607 nil); // context for async operations
608end;
609
610
611function TWinHTTPRequestImpl.WriteExtraData( const pBuf : Pointer; const dwBytes : DWORD) : DWORD;
612begin
613 if not WinHttpWriteData( FHandle, pBuf, dwBytes, result)
614 then result := 0;
615end;
616
617
618function TWinHTTPRequestImpl.FlushAndReceiveResponse : Boolean;
619begin
620 result := WinHttpReceiveResponse( FHandle, nil);
621end;
622
623
624function TWinHTTPRequestImpl.ReadData( const dwRead : DWORD) : TBytes;
625var dwAvailable, dwReceived : DWORD;
626begin
627 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
628 then dwAvailable := Min( dwRead, dwAvailable)
629 else dwAvailable := 0;
630
631 SetLength( result, dwAvailable);
632 if dwAvailable = 0 then Exit;
633
634 if WinHttpReadData( FHandle, @result[0], Length(result), dwReceived)
635 then SetLength( result, dwReceived)
636 else SetLength( result, 0);
637end;
638
639
640function TWinHTTPRequestImpl.ReadData( const pBuf : Pointer; const dwRead : DWORD) : DWORD;
641var dwAvailable : DWORD;
642begin
643 if WinHttpQueryDataAvailable( FHandle, dwAvailable)
644 then dwAvailable := Min( dwRead, dwAvailable)
645 else dwAvailable := 0;
646
647 if (dwAvailable = 0)
648 or not WinHttpReadData( FHandle, pBuf, dwAvailable, result)
649 then result := 0;
650end;
651
652
653{ TWinHTTPUrlImpl }
654
655constructor TWinHTTPUrlImpl.Create(const aUri: UnicodeString);
656begin
657 inherited Create;
658 CrackUrl( aUri)
659end;
660
661
662destructor TWinHTTPUrlImpl.Destroy;
663begin
664 inherited Destroy;
665end;
666
667
668procedure TWinHTTPUrlImpl.CrackURL( const value : UnicodeString);
669const FLAGS = 0; // no special operations, leave components as-is
670var components : URL_COMPONENTS;
671begin
672 FillChar(components, SizeOf(components), 0);
673 components.dwStructSize := SizeOf(components);
674
675 if value <> '' then begin
676 { For the WinHttpCrackUrl function, [...] if the pointer member is NULL but the
677 length member is not zero, both the pointer and length members are returned. }
678 components.dwSchemeLength := DWORD(-1);
679 components.dwHostNameLength := DWORD(-1);
680 components.dwUserNameLength := DWORD(-1);
681 components.dwPasswordLength := DWORD(-1);
682 components.dwUrlPathLength := DWORD(-1);
683 components.dwExtraInfoLength := DWORD(-1);
684
685 WinHttpCrackUrl( PWideChar(value), Length(value), FLAGS, components);
686 end;
687
688 FNumScheme := components.nScheme;
689 FPort := components.nPort;
690 SetString( FScheme, components.lpszScheme, components.dwSchemeLength);
691 SetString( FHostName, components.lpszHostName, components.dwHostNameLength);
692 SetString( FUserName, components.lpszUserName, components.dwUserNameLength);
693 SetString( FPassword, components.lpszPassword, components.dwPasswordLength);
694 SetString( FUrlPath, components.lpszUrlPath, components.dwUrlPathLength);
695 SetString( FExtraInfo, components.lpszExtraInfo, components.dwExtraInfoLength);
696end;
697
698
699function TWinHTTPUrlImpl.BuildUrl : UnicodeString;
700const FLAGS = 0; // no special operations, leave components as-is
701var components : URL_COMPONENTS;
702 dwChars : DWORD;
703begin
704 FillChar(components, SizeOf(components), 0);
705 components.dwStructSize := SizeOf(components);
706 components.lpszScheme := PWideChar(FScheme);
707 components.dwSchemeLength := Length(FScheme);
708 components.lpszHostName := PWideChar(FHostName);
709 components.dwHostNameLength := Length(FHostName);
710 components.nPort := FPort;
711 components.lpszUserName := PWideChar(FUserName);
712 components.dwUserNameLength := Length(FUserName);
713 components.lpszPassword := PWideChar(FPassword);
714 components.dwPasswordLength := Length(FPassword);
715 components.lpszUrlPath := PWideChar(FUrlPath);
716 components.dwUrlPathLength := Length(FUrlPath);
717 components.lpszExtraInfo := PWideChar(FExtraInfo);
718 components.dwExtraInfoLength := Length(FExtraInfo);
719
720 WinHttpCreateUrl( components, FLAGS, nil, dwChars);
721 if dwChars = 0
722 then result := ''
723 else begin
724 SetLength( result, dwChars + 1);
725 WinHttpCreateUrl( components, FLAGS, @result[1], dwChars);
726 SetLength( result, dwChars); // cut off terminating #0
727 end;
728end;
729
730
731function TWinHTTPUrlImpl.GetExtraInfo: UnicodeString;
732begin
733 result := FExtraInfo;
734end;
735
736function TWinHTTPUrlImpl.GetHostName: UnicodeString;
737begin
738 result := FHostName;
739end;
740
741function TWinHTTPUrlImpl.GetNumScheme: INTERNET_SCHEME;
742begin
743 result := FNumScheme;
744end;
745
746function TWinHTTPUrlImpl.GetPassword: UnicodeString;
747begin
748 result := FPassword;
749end;
750
751function TWinHTTPUrlImpl.GetPort: INTERNET_PORT;
752begin
753 result := FPort;
754end;
755
756function TWinHTTPUrlImpl.GetScheme: UnicodeString;
757begin
758 result := FScheme;
759end;
760
761function TWinHTTPUrlImpl.GetUrlPath: UnicodeString;
762begin
763 result := FUrlPath;
764end;
765
766function TWinHTTPUrlImpl.GetUserName: UnicodeString;
767begin
768 result := FUserName;
769end;
770
771procedure TWinHTTPUrlImpl.SetExtraInfo(const value: UnicodeString);
772begin
773 FExtraInfo := value;
774end;
775
776procedure TWinHTTPUrlImpl.SetHostName(const value: UnicodeString);
777begin
778 FHostName := value;
779end;
780
781procedure TWinHTTPUrlImpl.SetPassword(const value: UnicodeString);
782begin
783 FPassword := value;
784end;
785
786procedure TWinHTTPUrlImpl.SetPort(const value: INTERNET_PORT);
787begin
788 FPort := value;
789end;
790
791procedure TWinHTTPUrlImpl.SetScheme(const value: UnicodeString);
792begin
793 FScheme := value;
794end;
795
796procedure TWinHTTPUrlImpl.SetUrlPath(const value: UnicodeString);
797begin
798 FUrlPath := value;
799end;
800
801procedure TWinHTTPUrlImpl.SetUserName(const value: UnicodeString);
802begin
803 FUserName := value;
804end;
805
806
807end.
808