simplifying OSHTtpHandler (a bit), adding query string matching,
adapting OSHttpXmlRpcHandler accordingly. NOTE: this code is not live.0.6.0-stable
parent
df1485fc51
commit
0ea73384d4
|
@ -92,6 +92,16 @@ namespace OpenSim.Framework.Servers
|
||||||
}
|
}
|
||||||
protected Regex _path;
|
protected Regex _path;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dictionary of (query name, regular expression) tuples,
|
||||||
|
/// allowing us to match on URI query fields.
|
||||||
|
/// </summary>
|
||||||
|
public virtual Dictionary<string, Regex> Query
|
||||||
|
{
|
||||||
|
get { return _query; }
|
||||||
|
}
|
||||||
|
protected Dictionary<string, Regex> _query;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Dictionary of (header name, regular expression) tuples,
|
/// Dictionary of (header name, regular expression) tuples,
|
||||||
/// allowing us to match on HTTP header fields.
|
/// allowing us to match on HTTP header fields.
|
||||||
|
@ -118,18 +128,6 @@ namespace OpenSim.Framework.Servers
|
||||||
protected Regex _ipEndPointRegex;
|
protected Regex _ipEndPointRegex;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// An OSHttpHandler that matches on the "content-type" header can
|
|
||||||
/// supply an OSHttpContentTypeChecker delegate which will be
|
|
||||||
/// invoked by the request matcher in OSHttpRequestPump.
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>true if the handler is interested in the content;
|
|
||||||
/// false otherwise</returns>
|
|
||||||
internal virtual OSHttpContentTypeChecker ContentTypeChecker
|
|
||||||
{
|
|
||||||
get { return null; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base class constructor.
|
/// Base class constructor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -175,18 +175,13 @@ namespace OpenSim.Framework.Servers
|
||||||
_log.DebugFormat("[{0}] MatchHandlers for {1}", EngineID, req);
|
_log.DebugFormat("[{0}] MatchHandlers for {1}", EngineID, req);
|
||||||
foreach (OSHttpHandler h in handlers)
|
foreach (OSHttpHandler h in handlers)
|
||||||
{
|
{
|
||||||
Regex methodRegex = h.Method;
|
|
||||||
Regex pathRegex = h.Path;
|
|
||||||
Dictionary<string, Regex> headerRegexs = h.Headers;
|
|
||||||
Regex endPointsRegex = h.IPEndPointWhitelist;
|
|
||||||
|
|
||||||
// initial anchor
|
// initial anchor
|
||||||
scoredHandlers[h] = 0;
|
scoredHandlers[h] = 0;
|
||||||
|
|
||||||
// first, check whether IPEndPointWhitelist applies
|
// first, check whether IPEndPointWhitelist applies
|
||||||
// and, if it does, whether client is on that white
|
// and, if it does, whether client is on that white
|
||||||
// list.
|
// list.
|
||||||
if (null != endPointsRegex)
|
if (null != h.IPEndPointWhitelist)
|
||||||
{
|
{
|
||||||
// TODO: following code requires code changes to
|
// TODO: following code requires code changes to
|
||||||
// HttpServer.HttpRequest to become functional
|
// HttpServer.HttpRequest to become functional
|
||||||
|
@ -194,84 +189,65 @@ namespace OpenSim.Framework.Servers
|
||||||
IPEndPoint remote = req.RemoteIPEndPoint;
|
IPEndPoint remote = req.RemoteIPEndPoint;
|
||||||
if (null != remote)
|
if (null != remote)
|
||||||
{
|
{
|
||||||
Match epm = endPointsRegex.Match(remote.ToString());
|
Match epm = h.IPEndPointWhitelist.Match(remote.ToString());
|
||||||
if (!epm.Success) continue;
|
if (!epm.Success)
|
||||||
|
{
|
||||||
|
scoredHandlers.Remove(h);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (null != methodRegex)
|
if (null != h.Method)
|
||||||
{
|
{
|
||||||
Match m = methodRegex.Match(req.HttpMethod);
|
Match m = h.Method.Match(req.HttpMethod);
|
||||||
if (!m.Success) continue;
|
if (!m.Success)
|
||||||
|
{
|
||||||
|
scoredHandlers.Remove(h);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
scoredHandlers[h]++;
|
scoredHandlers[h]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// whitelist ok, now check path
|
// whitelist ok, now check path
|
||||||
if (null != pathRegex)
|
if (null != h.Path)
|
||||||
{
|
{
|
||||||
Match m = pathRegex.Match(req.RawUrl);
|
Match m = h.Path.Match(req.RawUrl);
|
||||||
if (!m.Success) continue;
|
if (!m.Success)
|
||||||
|
|
||||||
scoredHandlers[h] = m.ToString().Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// whitelist & path ok, now check headers
|
|
||||||
if (null != headerRegexs)
|
|
||||||
{
|
|
||||||
int headersMatch = 0;
|
|
||||||
|
|
||||||
// go through all header Regexs and evaluate
|
|
||||||
// match:
|
|
||||||
// if header field not present or does not match:
|
|
||||||
// remove handler from scoredHandlers
|
|
||||||
// continue
|
|
||||||
// else:
|
|
||||||
// add increment headersMatch
|
|
||||||
NameValueCollection headers = req.HttpRequest.Headers;
|
|
||||||
foreach (string tag in headerRegexs.Keys)
|
|
||||||
{
|
{
|
||||||
// do we have a header "tag"?
|
scoredHandlers.Remove(h);
|
||||||
if (null == headers[tag])
|
|
||||||
{
|
|
||||||
// no: remove the handler if it was added
|
|
||||||
// earlier and on to the next one
|
|
||||||
_log.DebugFormat("[{0}] dropping handler for {1}: null {2} header field: {3}", EngineID, req, tag, h);
|
|
||||||
|
|
||||||
scoredHandlers.Remove(h);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// does the content of header "tag" match
|
|
||||||
// the supplied regex?
|
|
||||||
Match hm = headerRegexs[tag].Match(headers[tag]);
|
|
||||||
if (!hm.Success) {
|
|
||||||
// no: remove the handler if it was added
|
|
||||||
// earlier and on to the next one
|
|
||||||
_log.DebugFormat("[{0}] dropping handler for {1}: {2} header field content \"{3}\" does not match regex {4}: {5}",
|
|
||||||
EngineID, req, tag, headers[tag], headerRegexs[tag].ToString(), h);
|
|
||||||
scoredHandlers.Remove(h);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we are looking at the "content-type" tag,
|
|
||||||
// check wether h has a ContentTypeChecker and
|
|
||||||
// invoke it if it has
|
|
||||||
if ((null != h.ContentTypeChecker) && !h.ContentTypeChecker(req))
|
|
||||||
{
|
|
||||||
scoredHandlers.Remove(h);
|
|
||||||
_log.DebugFormat("[{0}] dropping handler for {1}: content checker returned false: {2}", EngineID, req, h);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ok: header matches
|
|
||||||
headersMatch++;
|
|
||||||
_log.DebugFormat("[{0}] MatchHandlers: found handler for {1}: {2}", EngineID, req, h.ToString());
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// check whether h got kicked out
|
scoredHandlers[h] += m.ToString().Length;
|
||||||
if (!scoredHandlers.ContainsKey(h)) continue;
|
}
|
||||||
|
|
||||||
|
// whitelist & path ok, now check query string
|
||||||
|
if (null != h.Query)
|
||||||
|
{
|
||||||
|
int queriesMatch = MatchOnNameValueCollection(req.QueryString, h.Query);
|
||||||
|
if (0 == queriesMatch)
|
||||||
|
{
|
||||||
|
_log.DebugFormat("[{0}] request {1}", EngineID, req);
|
||||||
|
_log.DebugFormat("[{0}] dropping handler {1}", EngineID, h);
|
||||||
|
|
||||||
|
scoredHandlers.Remove(h);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
scoredHandlers[h] += queriesMatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// whitelist, path, query string ok, now check headers
|
||||||
|
if (null != h.Headers)
|
||||||
|
{
|
||||||
|
int headersMatch = MatchOnNameValueCollection(req.Headers, h.Headers);
|
||||||
|
if (0 == headersMatch)
|
||||||
|
{
|
||||||
|
_log.DebugFormat("[{0}] request {1}", EngineID, req);
|
||||||
|
_log.DebugFormat("[{0}] dropping handler {1}", EngineID, h);
|
||||||
|
|
||||||
|
scoredHandlers.Remove(h);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
scoredHandlers[h] += headersMatch;
|
scoredHandlers[h] += headersMatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -285,6 +261,33 @@ namespace OpenSim.Framework.Servers
|
||||||
return matchingHandlers;
|
return matchingHandlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected int MatchOnNameValueCollection(NameValueCollection collection, Dictionary<string, Regex> regexs)
|
||||||
|
{
|
||||||
|
int matched = 0;
|
||||||
|
|
||||||
|
foreach (string tag in regexs.Keys)
|
||||||
|
{
|
||||||
|
// do we have a header "tag"?
|
||||||
|
if (null == collection[tag])
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// does the content of collection[tag] match
|
||||||
|
// the supplied regex?
|
||||||
|
Match cm = regexs[tag].Match(collection[tag]);
|
||||||
|
if (!cm.Success) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ok: matches
|
||||||
|
matched++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
|
||||||
[ConditionalAttribute("DEBUGGING")]
|
[ConditionalAttribute("DEBUGGING")]
|
||||||
private void LogDumpHandlerList(List<OSHttpHandler> l)
|
private void LogDumpHandlerList(List<OSHttpHandler> l)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,48 +51,42 @@ namespace OpenSim.Framework.Servers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>true if the handler is interested in the content;
|
/// <returns>true if the handler is interested in the content;
|
||||||
/// false otherwise</returns>
|
/// false otherwise</returns>
|
||||||
internal override OSHttpContentTypeChecker ContentTypeChecker
|
protected bool XmlRpcMethodMatch(OSHttpRequest req)
|
||||||
{
|
{
|
||||||
get
|
XmlRpcRequest xmlRpcRequest = null;
|
||||||
{
|
|
||||||
return delegate(OSHttpRequest req)
|
// check whether req is already reified
|
||||||
|
// if not: reify (and post to whiteboard)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (req.Whiteboard.ContainsKey("xmlrequest"))
|
||||||
{
|
{
|
||||||
XmlRpcRequest xmlRpcRequest = null;
|
xmlRpcRequest = req.Whiteboard["xmlrequest"] as XmlRpcRequest;
|
||||||
|
}
|
||||||
// check whether req is already reified
|
else
|
||||||
// if not: reify (and post to whiteboard)
|
{
|
||||||
try
|
StreamReader body = new StreamReader(req.InputStream);
|
||||||
{
|
string requestBody = body.ReadToEnd();
|
||||||
if (req.Whiteboard.ContainsKey("xmlrequest"))
|
xmlRpcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody);
|
||||||
{
|
req.Whiteboard["xmlrequest"] = xmlRpcRequest;
|
||||||
xmlRpcRequest = req.Whiteboard["xmlrequest"] as XmlRpcRequest;
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StreamReader body = new StreamReader(req.InputStream);
|
|
||||||
string requestBody = body.ReadToEnd();
|
|
||||||
xmlRpcRequest = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(requestBody);
|
|
||||||
req.Whiteboard["xmlrequest"] = xmlRpcRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (XmlException)
|
|
||||||
{
|
|
||||||
_log.ErrorFormat("[OSHttpXmlRpcHandler] failed to deserialize XmlRpcRequest from {0}", req.ToString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check against methodName
|
|
||||||
if ((null != xmlRpcRequest)
|
|
||||||
&& !String.IsNullOrEmpty(xmlRpcRequest.MethodName)
|
|
||||||
&& xmlRpcRequest.MethodName == _methodName)
|
|
||||||
{
|
|
||||||
_log.DebugFormat("[OSHttpXmlRpcHandler] located handler {0} for {1}", _methodName, req.ToString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
catch (XmlException)
|
||||||
|
{
|
||||||
|
_log.ErrorFormat("[OSHttpXmlRpcHandler] failed to deserialize XmlRpcRequest from {0}", req.ToString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check against methodName
|
||||||
|
if ((null != xmlRpcRequest)
|
||||||
|
&& !String.IsNullOrEmpty(xmlRpcRequest.MethodName)
|
||||||
|
&& xmlRpcRequest.MethodName == _methodName)
|
||||||
|
{
|
||||||
|
_log.DebugFormat("[OSHttpXmlRpcHandler] located handler {0} for {1}", _methodName, req.ToString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// contains handler for processing XmlRpc Request
|
// contains handler for processing XmlRpc Request
|
||||||
|
@ -149,8 +143,11 @@ namespace OpenSim.Framework.Servers
|
||||||
XmlRpcResponse xmlRpcResponse;
|
XmlRpcResponse xmlRpcResponse;
|
||||||
string responseString;
|
string responseString;
|
||||||
|
|
||||||
|
// check whether we are interested in this request
|
||||||
|
if (!XmlRpcMethodMatch(request)) return OSHttpHandlerResult.Pass;
|
||||||
|
|
||||||
|
|
||||||
OSHttpResponse resp = new OSHttpResponse(request);
|
OSHttpResponse resp = new OSHttpResponse(request);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// reified XmlRpcRequest must still be on the whiteboard
|
// reified XmlRpcRequest must still be on the whiteboard
|
||||||
|
|
Loading…
Reference in New Issue