Refactor scripted http request to use async calls rather than hard threads

avinationmerge
Melanie 2013-01-20 02:08:38 +01:00
parent 903cc71f0d
commit 461ecd7cf9
1 changed files with 87 additions and 53 deletions

View File

@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
m_pendingRequests.Add(reqID, htc); m_pendingRequests.Add(reqID, htc);
} }
htc.Process(); htc.SendRequest();
return reqID; return reqID;
} }
@ -340,7 +340,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public string HttpMIMEType = "text/plain;charset=utf-8"; public string HttpMIMEType = "text/plain;charset=utf-8";
public int HttpTimeout; public int HttpTimeout;
public bool HttpVerifyCert = true; public bool HttpVerifyCert = true;
private Thread httpThread;
// Request info // Request info
private UUID _itemID; private UUID _itemID;
@ -374,27 +373,11 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
public void Process() public void Process()
{ {
httpThread = new Thread(SendRequest); SendRequest();
httpThread.Name = "HttpRequestThread";
httpThread.Priority = ThreadPriority.BelowNormal;
httpThread.IsBackground = true;
_finished = false;
httpThread.Start();
} }
/*
* TODO: More work on the response codes. Right now
* returning 200 for success or 499 for exception
*/
public void SendRequest() public void SendRequest()
{ {
HttpWebResponse response = null;
StringBuilder sb = new StringBuilder();
byte[] buf = new byte[8192];
string tempString = null;
int count = 0;
try try
{ {
Request = (HttpWebRequest) WebRequest.Create(Url); Request = (HttpWebRequest) WebRequest.Create(Url);
@ -409,13 +392,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
{ {
// We could hijack Connection Group Name to identify // We could hijack Connection Group Name to identify
// a desired security exception. But at the moment we'll use a dummy header instead. // a desired security exception. But at the moment we'll use a dummy header instead.
// Request.ConnectionGroupName = "NoVerify";
Request.Headers.Add("NoVerifyCert", "true"); Request.Headers.Add("NoVerifyCert", "true");
} }
// else
// {
// Request.ConnectionGroupName="Verify";
// }
if (proxyurl != null && proxyurl.Length > 0) if (proxyurl != null && proxyurl.Length > 0)
{ {
if (proxyexcepts != null && proxyexcepts.Length > 0) if (proxyexcepts != null && proxyexcepts.Length > 0)
@ -430,10 +409,14 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
} }
foreach (KeyValuePair<string, string> entry in ResponseHeaders) foreach (KeyValuePair<string, string> entry in ResponseHeaders)
{
if (entry.Key.ToLower().Equals("user-agent")) if (entry.Key.ToLower().Equals("user-agent"))
Request.UserAgent = entry.Value; Request.UserAgent = entry.Value;
else else
Request.Headers[entry.Key] = entry.Value; Request.Headers[entry.Key] = entry.Value;
}
Request.Timeout = HttpTimeout;
// Encode outbound data // Encode outbound data
if (OutboundBody.Length > 0) if (OutboundBody.Length > 0)
@ -441,16 +424,78 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
byte[] data = Util.UTF8.GetBytes(OutboundBody); byte[] data = Util.UTF8.GetBytes(OutboundBody);
Request.ContentLength = data.Length; Request.ContentLength = data.Length;
Stream bstream = Request.GetRequestStream(); Request.BeginGetRequestStream(new AsyncCallback(SendRequestData), this);
bstream.Write(data, 0, data.Length); return;
bstream.Close();
} }
Request.Timeout = HttpTimeout; Request.BeginGetResponse(new AsyncCallback(ProcessResponse), this);
}
catch (Exception e)
{
// Do nothing. Abort was called.
}
}
private void SendRequestData(IAsyncResult ar)
{
try
{
byte[] data = Util.UTF8.GetBytes(OutboundBody);
Stream bstream = Request.EndGetRequestStream(ar);
bstream.Write(data, 0, data.Length);
bstream.Close();
Request.BeginGetResponse(new AsyncCallback(ProcessResponse), this);
}
catch (WebException e)
{
// Abort was called. Just go away
if (e.Status == WebExceptionStatus.RequestCanceled)
return;
// Server errored on request
if (e.Status == WebExceptionStatus.ProtocolError && e.Response != null)
{
HttpWebResponse webRsp = (HttpWebResponse)e.Response;
Status = (int)webRsp.StatusCode;
try
{
using (Stream responseStream = webRsp.GetResponseStream())
{
ResponseBody = responseStream.GetStreamString();
}
}
catch
{
ResponseBody = webRsp.StatusDescription;
}
finally
{
webRsp.Close();
}
return;
}
_finished = true;
}
}
private void ProcessResponse(IAsyncResult ar)
{
HttpWebResponse response = null;
StringBuilder sb = new StringBuilder();
byte[] buf = new byte[8192];
string tempString = null;
int count = 0;
try
{
try try
{ {
// execute the request response = (HttpWebResponse) Request.EndGetResponse(ar);
response = (HttpWebResponse) Request.GetResponse();
} }
catch (WebException e) catch (WebException e)
{ {
@ -485,33 +530,22 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
ResponseBody = sb.ToString().Replace("\r", ""); ResponseBody = sb.ToString().Replace("\r", "");
} }
catch (Exception e) catch (WebException e)
{ {
if (e is WebException && ((WebException)e).Status == WebExceptionStatus.ProtocolError) // Abort was called. Just go away
{ if (e.Status == WebExceptionStatus.RequestCanceled)
HttpWebResponse webRsp = (HttpWebResponse)((WebException)e).Response; return;
Status = (int)webRsp.StatusCode;
try
{
using (Stream responseStream = webRsp.GetResponseStream())
{
ResponseBody = responseStream.GetStreamString();
}
}
catch
{
ResponseBody = webRsp.StatusDescription;
}
}
else
{
Status = (int)OSHttpStatusCode.ClientErrorJoker;
ResponseBody = e.Message;
}
Status = (int)OSHttpStatusCode.ClientErrorJoker;
ResponseBody = e.Message;
_finished = true; _finished = true;
return; return;
} }
catch (Exception e)
{
// Ignore
}
finally finally
{ {
if (response != null) if (response != null)
@ -525,7 +559,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest
{ {
try try
{ {
httpThread.Abort(); Request.Abort();
} }
catch (Exception) catch (Exception)
{ {