Skip to content

Commit e4735ec

Browse files
committed
Merge branch 'feature/http' into develop
2 parents 8cb3107 + 579d119 commit e4735ec

14 files changed

+1120
-3
lines changed
Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
using ScriptEngine.Machine;
2+
using ScriptEngine.Machine.Contexts;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Net;
7+
using System.Text;
8+
9+
namespace ScriptEngine.HostedScript.Library.Http
10+
{
11+
[ContextClass("HTTPСоединение", "HTTPConnection")]
12+
public class HttpConnectionContext : AutoContext<HttpConnectionContext>
13+
{
14+
InternetProxyContext _proxy;
15+
Uri _hostUri;
16+
17+
const string HTTP_SCHEME = "http";
18+
const string HTTPS_SCHEME = "https";
19+
20+
public HttpConnectionContext(string host,
21+
int port = 0,
22+
string user = null,
23+
string password = null,
24+
InternetProxyContext proxy = null,
25+
int timeout = 0)
26+
{
27+
var uriBuilder = new UriBuilder(host);
28+
if (port != 0)
29+
uriBuilder.Port = port;
30+
31+
if (uriBuilder.Scheme != HTTP_SCHEME && uriBuilder.Scheme != HTTPS_SCHEME)
32+
throw RuntimeException.InvalidArgumentValue();
33+
34+
_hostUri = uriBuilder.Uri;
35+
36+
Host = _hostUri.Host;
37+
Port = _hostUri.Port;
38+
39+
User = user == null ? String.Empty : user;
40+
Password = password == null ? String.Empty : password;
41+
Timeout = timeout;
42+
_proxy = proxy;
43+
44+
}
45+
46+
[ContextProperty("Пользователь","User")]
47+
public string User
48+
{
49+
get; private set;
50+
}
51+
52+
[ContextProperty("Пароль", "Password")]
53+
public string Password
54+
{
55+
get; private set;
56+
57+
}
58+
59+
[ContextProperty("Сервер", "Host")]
60+
public string Host
61+
{
62+
get; private set;
63+
}
64+
65+
[ContextProperty("Порт", "Port")]
66+
public int Port
67+
{
68+
get; private set;
69+
}
70+
71+
[ContextProperty("Прокси", "Proxy")]
72+
public IValue Proxy
73+
{
74+
get
75+
{
76+
if (_proxy == null)
77+
return ValueFactory.Create();
78+
79+
return _proxy;
80+
}
81+
}
82+
83+
[ContextProperty("Таймаут", "Timeout")]
84+
public int Timeout
85+
{
86+
get; private set;
87+
}
88+
89+
[ContextMethod("Получить", "Get")]
90+
public HttpResponseContext Get(HttpRequestContext request, string output = null)
91+
{
92+
return GetResponse(request, "GET", output);
93+
}
94+
95+
[ContextMethod("Записать", "Put")]
96+
public HttpResponseContext Put(HttpRequestContext request)
97+
{
98+
return GetResponse(request, "PUT");
99+
}
100+
101+
[ContextMethod("ОтправитьДляОбработки", "Post")]
102+
public HttpResponseContext Post(HttpRequestContext request, string output = null)
103+
{
104+
return GetResponse(request, "POST", output);
105+
}
106+
107+
[ContextMethod("Удалить", "Delete")]
108+
public HttpResponseContext Delete(HttpRequestContext request, string output = null)
109+
{
110+
return GetResponse(request, "DELETE");
111+
}
112+
113+
private HttpWebRequest CreateRequest(string resource)
114+
{
115+
var uriBuilder = new UriBuilder(_hostUri);
116+
if(Port != 0)
117+
uriBuilder.Port = Port;
118+
119+
var resourceUri = new Uri(uriBuilder.Uri, resource);
120+
121+
var request = (HttpWebRequest)HttpWebRequest.Create(resourceUri);
122+
if(User != "" || Password != "")
123+
request.Credentials = new NetworkCredential(User, Password);
124+
125+
if(_proxy != null)
126+
request.Proxy = _proxy.GetProxy();
127+
128+
if (Timeout > 0)
129+
request.Timeout = Timeout;
130+
131+
return request;
132+
133+
}
134+
135+
private HttpResponseContext GetResponse(HttpRequestContext request, string method, string output = null)
136+
{
137+
var webRequest = CreateRequest(request.ResourceAddress);
138+
webRequest.Method = method;
139+
webRequest.KeepAlive = false;
140+
SetRequestHeaders(request, webRequest);
141+
SetRequestBody(request, webRequest);
142+
143+
HttpWebResponse response;
144+
145+
try
146+
{
147+
response = (HttpWebResponse)webRequest.GetResponse();
148+
}
149+
catch (WebException ex)
150+
{
151+
if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null)
152+
response = (HttpWebResponse)ex.Response;
153+
else
154+
throw;
155+
}
156+
157+
var responseContext = new HttpResponseContext(response, output);
158+
159+
return responseContext;
160+
161+
}
162+
163+
private static void SetRequestBody(HttpRequestContext request, HttpWebRequest webRequest)
164+
{
165+
var stream = request.Body;
166+
if (stream == null)
167+
{
168+
return; // тело не установлено
169+
}
170+
171+
using(stream)
172+
{
173+
if (stream.CanSeek)
174+
webRequest.ContentLength = stream.Length;
175+
176+
using(var requestStream = webRequest.GetRequestStream())
177+
{
178+
const int CHUNK_SIZE = 4096;
179+
byte[] buf = new byte[CHUNK_SIZE];
180+
181+
while(true)
182+
{
183+
int bytesRead = stream.Read(buf, 0, CHUNK_SIZE);
184+
if (bytesRead == 0)
185+
break;
186+
187+
requestStream.Write(buf, 0, bytesRead);
188+
189+
}
190+
}
191+
}
192+
}
193+
194+
private static void SetRequestHeaders(HttpRequestContext request, HttpWebRequest webRequest)
195+
{
196+
foreach (var item in request.Headers.Select(x => x.GetRawValue() as KeyAndValueImpl))
197+
{
198+
System.Diagnostics.Trace.Assert(item != null);
199+
200+
var key = item.Key.AsString();
201+
var value = item.Value.AsString();
202+
203+
switch(key.ToUpperInvariant())
204+
{
205+
case "CONTENT-TYPE":
206+
webRequest.ContentType = value;
207+
break;
208+
case "CONTENT-LENGTH":
209+
try
210+
{
211+
webRequest.ContentLength = Int32.Parse(value);
212+
}
213+
catch (FormatException)
214+
{
215+
throw new RuntimeException("Заголовок Content-Length задан неправильно");
216+
}
217+
break;
218+
case "ACCEPT":
219+
webRequest.Accept = value;
220+
break;
221+
case "EXPECT":
222+
webRequest.Expect = value;
223+
break;
224+
case "TRANSFER-ENCODING":
225+
webRequest.TransferEncoding = value;
226+
break;
227+
case "CONNECTION":
228+
webRequest.Connection = value;
229+
break;
230+
case "DATE":
231+
try
232+
{
233+
webRequest.Date = DateTime.Parse(value);
234+
}
235+
catch (FormatException)
236+
{
237+
throw new RuntimeException("Заголовок Date задан неправильно");
238+
}
239+
break;
240+
case "HOST":
241+
webRequest.Host = value;
242+
break;
243+
case "IF-MODIFIED-SINCE":
244+
try
245+
{
246+
webRequest.IfModifiedSince = DateTime.Parse(value);
247+
}
248+
catch (FormatException)
249+
{
250+
throw new RuntimeException("Заголовок If-Modified-Since задан неправильно");
251+
}
252+
break;
253+
case "RANGE":
254+
throw new NotImplementedException();
255+
case "REFERER":
256+
webRequest.Referer = value;
257+
break;
258+
case "USER-AGENT":
259+
webRequest.UserAgent = value;
260+
break;
261+
case "PROXY-CONNECTION":
262+
throw new NotImplementedException();
263+
default:
264+
webRequest.Headers.Set(key, value);
265+
break;
266+
267+
}
268+
269+
270+
271+
}
272+
}
273+
274+
[ScriptConstructor]
275+
public static HttpConnectionContext Constructor(IValue host,
276+
IValue port = null,
277+
IValue user = null,
278+
IValue password = null,
279+
IValue proxy = null,
280+
IValue timeout = null)
281+
{
282+
return new HttpConnectionContext(host.AsString(),
283+
ContextValuesMarshaller.ConvertParam<int>(port),
284+
ContextValuesMarshaller.ConvertParam<string>(user),
285+
ContextValuesMarshaller.ConvertParam<string>(password),
286+
ContextValuesMarshaller.ConvertParam<InternetProxyContext>(proxy),
287+
ContextValuesMarshaller.ConvertParam<int>(timeout)
288+
);
289+
}
290+
291+
}
292+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using ScriptEngine.Machine;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.IO;
5+
using System.Linq;
6+
using System.Text;
7+
8+
namespace ScriptEngine.HostedScript.Library.Http
9+
{
10+
interface IHttpRequestBody : IDisposable
11+
{
12+
IValue GetAsString();
13+
IValue GetAsBinary();
14+
IValue GetAsFilename();
15+
16+
Stream GetDataStream();
17+
}
18+
19+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using ScriptEngine.Machine;
2+
using System;
3+
4+
namespace ScriptEngine.HostedScript.Library.Http
5+
{
6+
class HttpRequestBodyBinary : IHttpRequestBody
7+
{
8+
BinaryDataContext _data;
9+
10+
public HttpRequestBodyBinary(BinaryDataContext data)
11+
{
12+
_data = data;
13+
}
14+
15+
public IValue GetAsString()
16+
{
17+
return ValueFactory.Create();
18+
}
19+
20+
public IValue GetAsBinary()
21+
{
22+
return _data;
23+
}
24+
25+
public IValue GetAsFilename()
26+
{
27+
return ValueFactory.Create();
28+
}
29+
30+
public System.IO.Stream GetDataStream()
31+
{
32+
var bytes = _data.Buffer;
33+
return new System.IO.MemoryStream(bytes);
34+
}
35+
36+
public void Dispose()
37+
{
38+
_data = null;
39+
}
40+
}
41+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using ScriptEngine.Machine;
2+
using System;
3+
using System.IO;
4+
5+
namespace ScriptEngine.HostedScript.Library.Http
6+
{
7+
class HttpRequestBodyFile : IHttpRequestBody
8+
{
9+
private FileStream _bodyOpenedFile;
10+
11+
public HttpRequestBodyFile(string filename)
12+
{
13+
_bodyOpenedFile = new FileStream(filename, FileMode.Open);
14+
}
15+
16+
public IValue GetAsString()
17+
{
18+
return ValueFactory.Create();
19+
}
20+
21+
public IValue GetAsBinary()
22+
{
23+
return ValueFactory.Create();
24+
}
25+
26+
public IValue GetAsFilename()
27+
{
28+
return ValueFactory.Create(_bodyOpenedFile.Name);
29+
}
30+
31+
public Stream GetDataStream()
32+
{
33+
return _bodyOpenedFile;
34+
}
35+
36+
public void Dispose()
37+
{
38+
_bodyOpenedFile.Dispose();
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)