blob: cdfb541887db30dea5eb0a8d6caf4ad8ebbd65a7 [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)
44 private
45 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;
55 protected
56 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;
62
63 procedure SetDnsResolveTimeout(const Value: Integer);
64 function GetDnsResolveTimeout: Integer;
65 procedure SetConnectionTimeout(const Value: Integer);
66 function GetConnectionTimeout: Integer;
67 procedure SetSendTimeout(const Value: Integer);
68 function GetSendTimeout: Integer;
69 procedure SetReadTimeout(const Value: Integer);
70 function GetReadTimeout: Integer;
71
72 function GetCustomHeaders: IThriftDictionary<string,string>;
73 procedure SendRequest;
74 property DnsResolveTimeout: Integer read GetDnsResolveTimeout write SetDnsResolveTimeout;
75 property ConnectionTimeout: Integer read GetConnectionTimeout write SetConnectionTimeout;
76 property SendTimeout: Integer read GetSendTimeout write SetSendTimeout;
77 property ReadTimeout: Integer read GetReadTimeout write SetReadTimeout;
78 property CustomHeaders: IThriftDictionary<string,string> read GetCustomHeaders;
79 public
80 constructor Create( const AUri: string);
81 destructor Destroy; override;
82 end;
83
84
85implementation
86
87
88{ TMsxmlHTTPClientImpl }
89
90constructor TMsxmlHTTPClientImpl.Create(const AUri: string);
91begin
92 inherited Create;
93 FUri := AUri;
94
95 // defaults according to MSDN
96 FDnsResolveTimeout := 0; // no timeout
97 FConnectionTimeout := 60 * 1000;
98 FSendTimeout := 30 * 1000;
99 FReadTimeout := 30 * 1000;
100
101 FCustomHeaders := TThriftDictionaryImpl<string,string>.Create;
102 FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
103end;
104
105function TMsxmlHTTPClientImpl.CreateRequest: IXMLHTTPRequest;
106var
107 pair : TPair<string,string>;
108 srvHttp : IServerXMLHTTPRequest;
109begin
110 {$IF CompilerVersion >= 21.0}
111 Result := CoServerXMLHTTP.Create;
112 {$ELSE}
113 Result := CoXMLHTTPRequest.Create;
114 {$IFEND}
115
116 // setting a timeout value to 0 (zero) means "no timeout" for that setting
117 if Supports( result, IServerXMLHTTPRequest, srvHttp)
118 then srvHttp.setTimeouts( DnsResolveTimeout, ConnectionTimeout, SendTimeout, ReadTimeout);
119
120 Result.open('POST', FUri, False, '', '');
121 Result.setRequestHeader( 'Content-Type', 'application/x-thrift');
122 Result.setRequestHeader( 'Accept', 'application/x-thrift');
123 Result.setRequestHeader( 'User-Agent', 'Delphi/IHTTPClient');
124
125 for pair in FCustomHeaders do begin
126 Result.setRequestHeader( pair.Key, pair.Value );
127 end;
128end;
129
130destructor TMsxmlHTTPClientImpl.Destroy;
131begin
132 Close;
133 inherited;
134end;
135
136function TMsxmlHTTPClientImpl.GetDnsResolveTimeout: Integer;
137begin
138 Result := FDnsResolveTimeout;
139end;
140
141procedure TMsxmlHTTPClientImpl.SetDnsResolveTimeout(const Value: Integer);
142begin
143 FDnsResolveTimeout := Value;
144end;
145
146function TMsxmlHTTPClientImpl.GetConnectionTimeout: Integer;
147begin
148 Result := FConnectionTimeout;
149end;
150
151procedure TMsxmlHTTPClientImpl.SetConnectionTimeout(const Value: Integer);
152begin
153 FConnectionTimeout := Value;
154end;
155
156function TMsxmlHTTPClientImpl.GetSendTimeout: Integer;
157begin
158 Result := FSendTimeout;
159end;
160
161procedure TMsxmlHTTPClientImpl.SetSendTimeout(const Value: Integer);
162begin
163 FSendTimeout := Value;
164end;
165
166function TMsxmlHTTPClientImpl.GetReadTimeout: Integer;
167begin
168 Result := FReadTimeout;
169end;
170
171procedure TMsxmlHTTPClientImpl.SetReadTimeout(const Value: Integer);
172begin
173 FReadTimeout := Value;
174end;
175
176function TMsxmlHTTPClientImpl.GetCustomHeaders: IThriftDictionary<string,string>;
177begin
178 Result := FCustomHeaders;
179end;
180
181function TMsxmlHTTPClientImpl.GetIsOpen: Boolean;
182begin
183 Result := True;
184end;
185
186procedure TMsxmlHTTPClientImpl.Open;
187begin
188 FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
189end;
190
191procedure TMsxmlHTTPClientImpl.Close;
192begin
193 FInputStream := nil;
194 FOutputStream := nil;
195end;
196
197procedure TMsxmlHTTPClientImpl.Flush;
198begin
199 try
200 SendRequest;
201 finally
202 FOutputStream := nil;
203 FOutputStream := TThriftStreamAdapterDelphi.Create( TMemoryStream.Create, True);
204 ASSERT( FOutputStream <> nil);
205 end;
206end;
207
208function TMsxmlHTTPClientImpl.Read( const pBuf : Pointer; const buflen : Integer; off: Integer; len: Integer): Integer;
209begin
210 if FInputStream = nil then begin
211 raise TTransportExceptionNotOpen.Create('No request has been sent');
212 end;
213
214 try
215 Result := FInputStream.Read( pBuf, buflen, off, len)
216 except
217 on E: Exception
218 do raise TTransportExceptionUnknown.Create(E.Message);
219 end;
220end;
221
222procedure TMsxmlHTTPClientImpl.SendRequest;
223var
224 xmlhttp : IXMLHTTPRequest;
225 ms : TMemoryStream;
226 a : TBytes;
227 len : Integer;
228begin
229 xmlhttp := CreateRequest;
230
231 ms := TMemoryStream.Create;
232 try
233 a := FOutputStream.ToArray;
234 len := Length(a);
235 if len > 0 then begin
236 ms.WriteBuffer( Pointer(@a[0])^, len);
237 end;
238 ms.Position := 0;
239 xmlhttp.send( IUnknown( TStreamAdapter.Create( ms, soReference )));
240 FInputStream := nil;
241 FInputStream := TThriftStreamAdapterCOM.Create( IUnknown( xmlhttp.responseStream) as IStream);
242 finally
243 ms.Free;
244 end;
245end;
246
247procedure TMsxmlHTTPClientImpl.Write( const pBuf : Pointer; off, len : Integer);
248begin
249 FOutputStream.Write( pBuf, off, len);
250end;
251
252
253
254end.
255