/// <summary> /// Return the best matching method handler for the given parameters. /// </summary> internal HTTPDelegate GetHandler(HTTPHostname Host, String URI, HTTPMethod HTTPMethod = null, Func <HTTPContentType[], HTTPContentType> HTTPContentTypeSelector = null, Action <IEnumerable <String> > ParsedURIParametersDelegate = null) { Host = Host ?? HTTPHostname.Any; URI = URI.IsNullOrEmpty() ? "/" : URI; HTTPMethod = HTTPMethod ?? HTTPMethod.GET; HTTPContentTypeSelector = HTTPContentTypeSelector ?? (v => HTTPContentType.HTML_UTF8); lock (Lock) { #region Get HostNode or "*" or fail HostnameNode _HostNode = null; if (!_HostnameNodes.TryGetValue(Host, out _HostNode)) { if (!_HostnameNodes.TryGetValue(HTTPHostname.Any, out _HostNode)) { return(null); } } //return GetErrorHandler(Host, URL, HTTPMethod, HTTPContentType, HTTPStatusCode.BadRequest); #endregion #region Try to find the best matching URLNode... var _RegexList = from __URLNode in _HostNode.URINodes.Values select new { URLNode = __URLNode, Regex = __URLNode.URIRegex }; var _AllTemplates = from _RegexTupel in _RegexList select new { URLNode = _RegexTupel.URLNode, Match = _RegexTupel.Regex.Match(URI) }; var _Matches = from _Match in _AllTemplates where _Match.Match.Success orderby 100 * _Match.URLNode.SortLength + _Match.URLNode.ParameterCount descending select new { URLNode = _Match.URLNode, Match = _Match.Match }; #endregion #region ...or return HostNode if (!_Matches.Any()) { //if (_HostNode.RequestHandler != null) // return _HostNode.RequestHandler; return(null); } #endregion HTTPMethodNode _HTTPMethodNode = null; ContentTypeNode _HTTPContentTypeNode = null; // Caused e.g. by the naming of the variables within the // URI templates, there could be multiple matches! //foreach (var _Match in _Matches) //{ // Use best matching URL Handler! var _Match2 = _Matches.First(); #region Copy MethodHandler Parameters var _Parameters = new List <String>(); for (var i = 1; i < _Match2.Match.Groups.Count; i++) { //_Parameters.Add(_Match2.Match.Groups[i].Value.RemoveLastSlash()); _Parameters.Add(_Match2.Match.Groups[i].Value); } var ParsedURIParametersDelegateLocal = ParsedURIParametersDelegate; if (ParsedURIParametersDelegateLocal != null) { ParsedURIParametersDelegate(_Parameters); } #endregion // If HTTPMethod was found... if (_Match2.URLNode.HTTPMethods.TryGetValue(HTTPMethod, out _HTTPMethodNode)) { var BestMatchingContentType = HTTPContentTypeSelector(_HTTPMethodNode.HTTPContentTypes.Keys.ToArray()); // Get HTTPContentTypeNode if (!_HTTPMethodNode.HTTPContentTypes.TryGetValue(BestMatchingContentType, out _HTTPContentTypeNode)) { return(_HTTPMethodNode.RequestHandler); } return(_HTTPContentTypeNode.RequestHandler); } //} // No HTTPMethod was found => return best matching URL Handler return(_Match2.URLNode.RequestHandler); //return GetErrorHandler(Host, URL, HTTPMethod, HTTPContentType, HTTPStatusCode.BadRequest); } }
// Method Callbacks #region (internal) AddHandler(HTTPDelegate, Hostname = "*", URITemplate = "/", HTTPMethod = null, HTTPContentType = null, HostAuthentication = null, URIAuthentication = null, HTTPMethodAuthentication = null, ContentTypeAuthentication = null, DefaultErrorHandler = null) /// <summary> /// Add a method callback for the given URI template. /// </summary> /// <param name="HTTPDelegate">A delegate called for each incoming HTTP request.</param> /// <param name="Hostname">The HTTP hostname.</param> /// <param name="URITemplate">The URI template.</param> /// <param name="HTTPMethod">The HTTP method.</param> /// <param name="HTTPContentType">The HTTP content type.</param> /// <param name="HostAuthentication">Whether this method needs explicit host authentication or not.</param> /// <param name="URIAuthentication">Whether this method needs explicit uri authentication or not.</param> /// <param name="HTTPMethodAuthentication">Whether this method needs explicit HTTP method authentication or not.</param> /// <param name="ContentTypeAuthentication">Whether this method needs explicit HTTP content type authentication or not.</param> /// <param name="DefaultErrorHandler">The default error handler.</param> internal void AddHandler(HTTPDelegate HTTPDelegate, HTTPHostname Hostname = null, String URITemplate = "/", HTTPMethod HTTPMethod = null, HTTPContentType HTTPContentType = null, HTTPAuthentication HostAuthentication = null, HTTPAuthentication URIAuthentication = null, HTTPAuthentication HTTPMethodAuthentication = null, HTTPAuthentication ContentTypeAuthentication = null, HTTPDelegate DefaultErrorHandler = null, URIReplacement AllowReplacement = URIReplacement.Fail) { lock (Lock) { #region Initial Checks if (HTTPDelegate == null) { throw new ArgumentNullException("HTTPDelegate", "The given parameter must not be null!"); } if (Hostname == null) { Hostname = HTTPHostname.Any; } if (URITemplate.IsNullOrEmpty()) { URITemplate = "/"; } if (HTTPMethod == null && HTTPContentType != null) { throw new ArgumentNullException("If HTTPMethod is null the HTTPContentType must also be null!"); } #endregion #region AddOrUpdate HostNode HostnameNode _HostnameNode = null; if (!_HostnameNodes.TryGetValue(Hostname, out _HostnameNode)) { _HostnameNode = new HostnameNode(Hostname, HostAuthentication, HTTPDelegate, DefaultErrorHandler); _HostnameNodes.Add(Hostname, _HostnameNode); } #endregion _HostnameNode.AddHandler(HTTPDelegate, URITemplate, HTTPMethod, HTTPContentType, URIAuthentication, HTTPMethodAuthentication, ContentTypeAuthentication, DefaultErrorHandler, AllowReplacement); } }
// Method Callbacks #region (internal) AddHandler(HTTPDelegate, Hostname = "*", URITemplate = "/", HTTPMethod = null, HTTPContentType = null, HostAuthentication = null, URIAuthentication = null, HTTPMethodAuthentication = null, ContentTypeAuthentication = null, DefaultErrorHandler = null) /// <summary> /// Add a method callback for the given URI template. /// </summary> /// <param name="HTTPDelegate">A delegate called for each incoming HTTP request.</param> /// <param name="Hostname">The HTTP hostname.</param> /// <param name="URITemplate">The URI template.</param> /// <param name="HTTPMethod">The HTTP method.</param> /// <param name="HTTPContentType">The HTTP content type.</param> /// <param name="HostAuthentication">Whether this method needs explicit host authentication or not.</param> /// <param name="URIAuthentication">Whether this method needs explicit uri authentication or not.</param> /// <param name="HTTPMethodAuthentication">Whether this method needs explicit HTTP method authentication or not.</param> /// <param name="ContentTypeAuthentication">Whether this method needs explicit HTTP content type authentication or not.</param> /// <param name="DefaultErrorHandler">The default error handler.</param> internal void AddHandler(HTTPDelegate HTTPDelegate, HTTPHostname Hostname = null, String URITemplate = "/", HTTPMethod HTTPMethod = null, HTTPContentType HTTPContentType = null, HTTPAuthentication HostAuthentication = null, HTTPAuthentication URIAuthentication = null, HTTPAuthentication HTTPMethodAuthentication = null, HTTPAuthentication ContentTypeAuthentication = null, HTTPDelegate DefaultErrorHandler = null, URIReplacement AllowReplacement = URIReplacement.Fail) { lock (Lock) { #region Initial Checks if (HTTPDelegate == null) throw new ArgumentNullException("HTTPDelegate", "The given parameter must not be null!"); if (Hostname == null) Hostname = HTTPHostname.Any; if (URITemplate.IsNullOrEmpty()) URITemplate = "/"; if (HTTPMethod == null && HTTPContentType != null) throw new ArgumentNullException("If HTTPMethod is null the HTTPContentType must also be null!"); #endregion #region AddOrUpdate HostNode HostnameNode _HostnameNode = null; if (!_HostnameNodes.TryGetValue(Hostname, out _HostnameNode)) { _HostnameNode = new HostnameNode(Hostname, HostAuthentication, HTTPDelegate, DefaultErrorHandler); _HostnameNodes.Add(Hostname, _HostnameNode); } #endregion _HostnameNode.AddHandler(HTTPDelegate, URITemplate, HTTPMethod, HTTPContentType, URIAuthentication, HTTPMethodAuthentication, ContentTypeAuthentication, DefaultErrorHandler, AllowReplacement); } }