blob: b92cce1e12b50b964d140579cb646579ed718fea [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.Transport.MsxmlHTTP;
20
21{$I Thrift.Defines.inc}
22{$SCOPEDENUMS ON}
23
24interface
25
26uses
27 Classes,
28 SysUtils,
29 Math,
30 Generics.Collections,
31 {$IFDEF OLD_UNIT_NAMES}
32 ActiveX, msxml,
33 {$ELSE}
34 Winapi.ActiveX, Winapi.msxml,
35 {$ENDIF}
36 Thrift.Collections,
37 Thrift.Transport,
38 Thrift.Exception,
39 Thrift.Utils,
40 Thrift.Stream;
41
42type
43 TMsxmlHTTPClientImpl = class( TTransportImpl, IHTTPClient)
Jens Geyerfad7fd32019-11-09 23:24:52 +010044 strict private
Jens Geyer02230912019-04-03 01:12:51 +020045 FUri : string;
46 FInputStream : IThriftStream;
47 FOutputStream : IThriftStream;
48 FDnsResolveTimeout : Integer;
49 FConnectionTimeout : Integer;
50 FSendTimeout : Integer;
51 FReadTimeout : Integer;
52 FCustomHeaders : IThriftDictionary<string,string>;
53
54 function CreateRequest: IXMLHTTPRequest;
Jens Geyerfad7fd32019-11-09 23:24:52 +010055 strict protected
Jens Geyer02230912019-04-03 01:12:51 +020056 function GetIsOpen: Boolean; override;
57 procedure Open(); override;
58 procedure Close(); override;
59 function Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer; override;
60 procedure Write( const pBuf : Pointer; off, len : Integer); override;
61 procedure Flush; override;
Jens Geyer41f47af2019-11-09 23:24:52 +010062 procedure CheckReadBytesAvailable( const value : Integer); override;
Jens Geyer02230912019-04-03 01:12:51 +020063
64 procedure SetDnsResolveTimeout(const Value: Integer);
65 function GetDnsResolveTimeout: Integer;
66 procedure SetConnectionTimeout(const Value: Integer);
67 function GetConnectionTimeout: Integer;
68 procedure SetSendTimeout(const Value: Integer);
69 function GetSendTimeout: Integer;
70 procedure SetReadTimeout(const Value: Integer);
71 function GetReadTimeout: Integer;
Jens Geyer47f63172019-06-06 22:42:58 +020072 function GetSecureProtocols : TSecureProtocols;
73 procedure SetSecureProtocols( const value : TSecureProtocols);
Jens Geyer02230912019-04-03 01:12:51 +020074
75 function GetCustomHeaders: IThriftDictionary<string,string>;
76 procedure SendRequest;
Jens Geyer47f63172019-06-06 22:42:58 +020077
Jens Geyer02230912019-04-03 01:12:51 +020078 property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
79 property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
80 property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
81 property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
82 property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
83 public
Jens Geyer41f47af2019-11-09 23:24:52 +010084 constructor Create( const AUri: string; const aTransportCtl : ITransportControl = nil);
Jens Geyer02230912019-04-03 01:12:51 +020085 destructor Destroy; override;
86 end;
87
88
89implementation
90
91
92{ TMsxmlHTTPClientImpl }
93
Jens Geyer41f47af2019-11-09 23:24:52 +010094constructor TMsxmlHTTPClientImpl.Create(const AUri: string; const aTransportCtl : ITransportControl);
Jens Geyer02230912019-04-03 01:12:51 +020095begin
Jens Geyer41f47af2019-11-09 23:24:52 +010096 inherited Create( aTransportCtl);
Jens Geyer02230912019-04-03 01:12:51 +020097 FUri := AUri;
98
99 // defaults according to MSDN
100 FDnsResolveTimeout := 0; // no timeout
101 FConnectionTimeout := 60 * 1000;
102 FSendTimeout := 30 * 1000;
103 FReadTimeout := 30 * 1000;
104
105 FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
106 FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
107end;
108
109function TMsxmlHTTPClientImpl.CreateRequest: IXMLHTTPRequest;
110var
111 pair : TPair<string,string>;
112 srvHttp : IServerXMLHTTPRequest;
113begin
114 {$IF CompilerVersion >= 21.0}
115 Result := CoServerXMLHTTP.Create;
116 {$ELSE}
117 Result := CoXMLHTTPRequest.Create;
118 {$IFEND}
119
120 // setting a timeout value to 0 (zero) means "no timeout" for that setting
121 if Supports( result, IServerXMLHTTPRequest, srvHttp)
122 then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout);
123
124 Result.open('POST', FUri, False, '', '');
Jens Geyer83ff7532019-06-06 22:46:03 +0200125 Result.setRequestHeader( 'Content-Type', THRIFT_MIMETYPE);
126 Result.setRequestHeader( 'Accept', THRIFT_MIMETYPE);
Jens Geyer02230912019-04-03 01:12:51 +0200127 Result.setRequestHeader( 'User-Agent', 'Delphi/IHTTPClient');
128
129 for pair in FCustomHeaders do begin
130 Result.setRequestHeader( pair.Key, pair.Value );
131 end;
132end;
133
134destructor TMsxmlHTTPClientImpl.Destroy;
135begin
136 Close;
137 inherited;
138end;
139
140function TMsxmlHTTPClientImpl.GetDnsResolveTimeout: Integer;
141begin
142 Result := FDnsResolveTimeout;
143end;
144
145procedure TMsxmlHTTPClientImpl.SetDnsResolveTimeout(const Value: Integer);
146begin
147 FDnsResolveTimeout := Value;
148end;
149
150function TMsxmlHTTPClientImpl.GetConnectionTimeout: Integer;
151begin
152 Result := FConnectionTimeout;
153end;
154
155procedure TMsxmlHTTPClientImpl.SetConnectionTimeout(const Value: Integer);
156begin
157 FConnectionTimeout := Value;
158end;
159
160function TMsxmlHTTPClientImpl.GetSendTimeout: Integer;
161begin
162 Result := FSendTimeout;
163end;
164
165procedure TMsxmlHTTPClientImpl.SetSendTimeout(const Value: Integer);
166begin
167 FSendTimeout := Value;
168end;
169
170function TMsxmlHTTPClientImpl.GetReadTimeout: Integer;
171begin
172 Result := FReadTimeout;
173end;
174
175procedure TMsxmlHTTPClientImpl.SetReadTimeout(const Value: Integer);
176begin
177 FReadTimeout := Value;
178end;
179
Jens Geyer47f63172019-06-06 22:42:58 +0200180function TMsxmlHTTPClientImpl.GetSecureProtocols : TSecureProtocols;
181begin
182 Result := [];
183end;
184
185procedure TMsxmlHTTPClientImpl.SetSecureProtocols( const value : TSecureProtocols);
186begin
187 raise TTransportExceptionBadArgs.Create('SetSecureProtocols: Not supported with '+ClassName);
188end;
189
Jens Geyer02230912019-04-03 01:12:51 +0200190function TMsxmlHTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
191begin
192 Result := FCustomHeaders;
193end;
194
195function TMsxmlHTTPClientImpl.GetIsOpen: Boolean;
196begin
197 Result := True;
198end;
199
200procedure TMsxmlHTTPClientImpl.Open;
201begin
202 FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
203end;
204
205procedure TMsxmlHTTPClientImpl.Close;
206begin
207 FInputStream := nil;
208 FOutputStream := nil;
209end;
210
211procedure TMsxmlHTTPClientImpl.Flush;
212begin
213 try
214 SendRequest;
215 finally
216 FOutputStream := nil;
217 FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
218 ASSERT( FOutputStream <> nil);
219 end;
220end;
221
Jens Geyer41f47af2019-11-09 23:24:52 +0100222procedure TMsxmlHTTPClientImpl.CheckReadBytesAvailable( const value : Integer);
223begin
224 if FInputStream <> nil
225 then FInputStream.CheckReadBytesAvailable( value)
226 else raise TTransportExceptionNotOpen.Create('No request has been sent');
227end;
228
Jens Geyer02230912019-04-03 01:12:51 +0200229function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
230begin
231 if FInputStream = nil then begin
232 raise TTransportExceptionNotOpen.Create('No request has been sent');
233 end;
234
235 try
Jens Geyer41f47af2019-11-09 23:24:52 +0100236 Result := FInputStream.Read( pBuf, buflen, off, len);
237 ConsumeReadBytes( result);
Jens Geyer02230912019-04-03 01:12:51 +0200238 except
239 on E: Exception
240 do raise TTransportExceptionUnknown.Create(E.Message);
241 end;
242end;
243
244procedure TMsxmlHTTPClientImpl.SendRequest;
245var
246 xmlhttp : IXMLHTTPRequest;
247 ms : TMemoryStream;
248 a : TBytes;
249 len : Integer;
250begin
251 xmlhttp := CreateRequest;
252
253 ms := TMemoryStream.Create;
254 try
255 a := FOutputStream.ToArray;
256 len := Length(a);
257 if len > 0 then begin
258 ms.WriteBuffer( Pointer(@a[0])^, len);
259 end;
260 ms.Position := 0;
261 xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference )));
262 FInputStream := nil;
263 FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream);
264 finally
265 ms.Free;
266 end;
267end;
268
269procedure TMsxmlHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer);
270begin
271 FOutputStream.Write( pBuf, off, len);
272end;
273
274
275
276end.
277