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;
|
||||
|
||||
/// <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>
|
||||
/// Dictionary of (header name, regular expression) tuples,
|
||||
/// allowing us to match on HTTP header fields.
|
||||
|
@ -118,18 +128,6 @@ namespace OpenSim.Framework.Servers
|
|||
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>
|
||||
/// Base class constructor.
|
||||
/// </summary>
|
||||
|
|
|
@ -175,18 +175,13 @@ namespace OpenSim.Framework.Servers
|
|||
_log.DebugFormat("[{0}] MatchHandlers for {1}", EngineID, req);
|
||||
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
|
||||
scoredHandlers[h] = 0;
|
||||
|
||||
// first, check whether IPEndPointWhitelist applies
|
||||
// and, if it does, whether client is on that white
|
||||
// list.
|
||||
if (null != endPointsRegex)
|
||||
if (null != h.IPEndPointWhitelist)
|
||||
{
|
||||
// TODO: following code requires code changes to
|
||||
// HttpServer.HttpRequest to become functional
|
||||
|
@ -194,84 +189,65 @@ namespace OpenSim.Framework.Servers
|
|||
IPEndPoint remote = req.RemoteIPEndPoint;
|
||||
if (null != remote)
|
||||
{
|
||||
Match epm = endPointsRegex.Match(remote.ToString());
|
||||
if (!epm.Success) continue;
|
||||
Match epm = h.IPEndPointWhitelist.Match(remote.ToString());
|
||||
if (!epm.Success)
|
||||
{
|
||||
scoredHandlers.Remove(h);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (null != methodRegex)
|
||||
if (null != h.Method)
|
||||
{
|
||||
Match m = methodRegex.Match(req.HttpMethod);
|
||||
if (!m.Success) continue;
|
||||
|
||||
Match m = h.Method.Match(req.HttpMethod);
|
||||
if (!m.Success)
|
||||
{
|
||||
scoredHandlers.Remove(h);
|
||||
continue;
|
||||
}
|
||||
scoredHandlers[h]++;
|
||||
}
|
||||
|
||||
// whitelist ok, now check path
|
||||
if (null != pathRegex)
|
||||
if (null != h.Path)
|
||||
{
|
||||
Match m = pathRegex.Match(req.RawUrl);
|
||||
if (!m.Success) continue;
|
||||
|
||||
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)
|
||||
Match m = h.Path.Match(req.RawUrl);
|
||||
if (!m.Success)
|
||||
{
|
||||
// do we have a header "tag"?
|
||||
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());
|
||||
scoredHandlers.Remove(h);
|
||||
continue;
|
||||
}
|
||||
// check whether h got kicked out
|
||||
if (!scoredHandlers.ContainsKey(h)) continue;
|
||||
scoredHandlers[h] += m.ToString().Length;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
@ -285,6 +261,33 @@ namespace OpenSim.Framework.Servers
|
|||
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")]
|
||||
private void LogDumpHandlerList(List<OSHttpHandler> l)
|
||||
{
|
||||
|
|
|
@ -51,48 +51,42 @@ namespace OpenSim.Framework.Servers
|
|||
/// </summary>
|
||||
/// <returns>true if the handler is interested in the content;
|
||||
/// false otherwise</returns>
|
||||
internal override OSHttpContentTypeChecker ContentTypeChecker
|
||||
{
|
||||
get
|
||||
{
|
||||
return delegate(OSHttpRequest req)
|
||||
protected bool XmlRpcMethodMatch(OSHttpRequest req)
|
||||
{
|
||||
XmlRpcRequest xmlRpcRequest = null;
|
||||
|
||||
// check whether req is already reified
|
||||
// if not: reify (and post to whiteboard)
|
||||
try
|
||||
{
|
||||
if (req.Whiteboard.ContainsKey("xmlrequest"))
|
||||
{
|
||||
XmlRpcRequest xmlRpcRequest = null;
|
||||
|
||||
// check whether req is already reified
|
||||
// if not: reify (and post to whiteboard)
|
||||
try
|
||||
{
|
||||
if (req.Whiteboard.ContainsKey("xmlrequest"))
|
||||
{
|
||||
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;
|
||||
};
|
||||
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;
|
||||
}
|
||||
|
||||
// contains handler for processing XmlRpc Request
|
||||
|
@ -149,8 +143,11 @@ namespace OpenSim.Framework.Servers
|
|||
XmlRpcResponse xmlRpcResponse;
|
||||
string responseString;
|
||||
|
||||
// check whether we are interested in this request
|
||||
if (!XmlRpcMethodMatch(request)) return OSHttpHandlerResult.Pass;
|
||||
|
||||
|
||||
OSHttpResponse resp = new OSHttpResponse(request);
|
||||
|
||||
try
|
||||
{
|
||||
// reified XmlRpcRequest must still be on the whiteboard
|
||||
|
|
Loading…
Reference in New Issue