-
Notifications
You must be signed in to change notification settings - Fork 1
/
Web.mORMot.Http.pas
182 lines (145 loc) · 5.29 KB
/
Web.mORMot.Http.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
unit Web.mORMot.Http;
{-------------------------------------------------------------------------------
mORMot for TMS WebCore.
Adapted from mORMot v1 CrossPlatform units.
See original file for copyright and licence information at:
https://github.com/synopse/mORMot
Note: Manual RTTI for SMS has been removed.
-------------------------------------------------------------------------------}
interface
uses
SysUtils,
JS,
Web,
Web.mORMot.RestTypes,
Web.mORMot.RestUtils,
Web.mORMot.HttpTypes;
type
/// abstract class for HTTP client connection
TAbstractHttpConnection = class
protected
fParameters: TRestConnectionParams;
fURL: string;
fOpaqueConnection: TObject;
public
/// this is the main entry point for all HTTP clients
// - connect to http://aServer:aPort or https://aServer:aPort
// - optional aProxyName may contain the name of the proxy server to use,
// and aProxyByPass an optional semicolon delimited list of host names or
// IP addresses, or both, that should not be routed through the proxy
constructor Create(const aParameters: TRestConnectionParams); virtual;
/// perform the request
// - this is the main entry point of this class
// - inherited classes should override this abstract method
procedure URI(var Call: TRestURIParams; const InDataType: string;
KeepAlive: integer); virtual; abstract;
/// the remote server full URI
// - e.g. 'http://myserver:888/'
property Server: string read fURL;
/// the connection parameters
property Parameters: TRestConnectionParams read fParameters;
/// opaque access to the effective connection class instance
// - which may be a TFPHttpClient, a TIdHTTP or a TWinHttpAPI
property ActualConnection: TObject read fOpaqueConnection;
end;
/// define the inherited class for HTTP client connection
TAbstractHttpConnectionClass = class of TAbstractHttpConnection;
// -- Note that we're only defining one connection class type for now.
{ TODO : Incorporate additional connection class types. }
TWebHttpConnectionClass = class(TAbstractHttpConnection)
protected // see http://www.w3.org/TR/XMLHttpRequest
public
procedure URI(var Call: TRestURIParams; const InDataType: string;
KeepAlive: integer); override;
end;
/// gives access to the class type to implement a HTTP connection
// - will use WinHTTP API (from our SynCrtSock) under Windows
// - will use Indy for Delphi on other platforms
// - will use fcl-web (fphttpclient) with FreePascal
function HttpConnectionClass: TAbstractHttpConnectionClass;
implementation
//------------------------------------------------------------------------------
{function HttpConnectionClass: TAbstractHttpConnectionClass;
begin
result := THttpClientHttpConnectionClass;
end;}
{ TAbstractHttpConnection }
//------------------------------------------------------------------------------
constructor TAbstractHttpConnection.Create(
const aParameters: TRestConnectionParams);
begin
inherited Create;
fParameters := aParameters;
if fParameters.Port = 0 then
if fParameters.Https then
fParameters.Port := INTERNET_DEFAULT_HTTPS_PORT else
fParameters.Port := INTERNET_DEFAULT_HTTP_PORT;
if fParameters.Https then
fURL := 'https://' else
fURL := 'http://';
fURL := fURL + fParameters.Server + ':' + IntToStr(fParameters.Port) + '/';
end;
{ TWebHttpConnectionClass } // - formerly TSMSHttpConnectionClass.
{ TODO : Implement Call.XHR.onerror }
//------------------------------------------------------------------------------
procedure TWebHttpConnectionClass.URI(var Call: TRestURIParams;
const InDataType: string; KeepAlive: integer);
var
i: integer;
l: integer;
line: string;
head: string;
value: string;
begin
asm
Call.XHR = new XMLHttpRequest();
end;
if Assigned(Call.OnSuccess) then // asynchronous call
begin
Call.XHR.onreadystatechange :=
procedure
begin
if Call.XHR.readyState = Call.XHR.DONE then
begin
Call.XHR.onreadystatechange := nil; // avoid any further trigger
Call.OutStatus := Call.XHR.status;
Call.OutHead := Call.XHR.getAllResponseHeaders();
Call.OutBody := Call.XHR.responseText;
Call.OnSuccess;
end;
end;
//Call.XHR.onerror := Call.OnError;
Call.XHR.open(Call.Verb, fURL + Call.Url, true); // true for asynch call
end
else
Call.XHR.open(Call.Verb, fURL + Call.Url, false); // false for synch call
if Call.InHead <> '' then
begin
i := 1;
while GetNextCSV(Call.InHead, i, line, #10) do
begin
l := pos(':', line);
if l = 0 then
continue;
head := trim(copy(line, 1, l - 1));
value := trim(copy(line, l + 1, length(line)));
if (head <> '') and (value <> '') then
Call.XHR.setRequestHeader(head, value);
end;
end;
if Call.InBody = '' then
Call.XHR.send(null)
else
Call.XHR.send(Call.InBody);
if not Assigned(Call.OnSuccess) then begin // synchronous call
Call.OutStatus := Call.XHR.status;
Call.OutHead := Call.XHR.getAllResponseHeaders();
Call.OutBody := Call.XHR.responseText;
end;
end;
//------------------------------------------------------------------------------
function HttpConnectionClass: TAbstractHttpConnectionClass;
begin
result := TWebHttpConnectionClass;
end;
end.