protected virtual void OnResponderException(ResponderExceptionEventArgs <TContext> e) { ResponderException?.Invoke(this, e); }
protected virtual void HandleRequest(TContext context) { var httpMethod = RequestHttpMethodFromContext(context); var realUrl = RequestUriFromContext(context); var availableMethodsForPath = new List <string>(); var path = realUrl.AbsolutePath; // strip multiple slashes while (path.StartsWith("//")) { path = path.Substring(1); } var lea = new HttpServerEventArgs <TContext>(context); OnRequestReceived(lea); if (lea.Responded) { return; } // find a handler foreach (var handler in Handlers) { Match match = handler.Matcher.Match(path); if (!match.Success) { continue; } // we found a match var argumentStrings = new Dictionary <string, string>(); foreach (string groupName in handler.ParameterNames) { argumentStrings[groupName] = match.Groups[groupName].Value; } ParameterInfo[] parameters = handler.Endpoint.GetParameters(); // this has been verified during adding Debug.Assert(parameters.Length > 0); Debug.Assert(parameters[0].ParameterType == typeof(TContext)); // add the context as the first argument value var argValues = new List <object> { context }; var failed = false; foreach (ParameterInfo argument in parameters.Skip(1)) { if (!handler.ParameterNames.Contains(argument.Name)) { // this has been verified during adding Debug.Assert(argument.HasDefaultValue); argValues.Add(argument.DefaultValue); continue; } string str = HttpDispatcherUtil.UrlDecodeUtf8(argumentStrings[argument.Name]); var e = new ParseValueEventArgs <TContext>(context, handler.Responder, handler.Endpoint, argument.Name, argument.ParameterType, str); OnParseValue(e); if (e.Responded) { return; } if (e.Parsed) { argValues.Add(str); continue; } // some defaults if (argument.ParameterType == typeof(string)) { argValues.Add(str); } else if (argument.ParameterType == typeof(int) || argument.ParameterType == typeof(int?)) { int?value = HttpDispatcherUtil.ParseIntOrNull(str); if (!value.HasValue) { failed = true; break; } argValues.Add(value.Value); } else if (argument.ParameterType == typeof(long) || argument.ParameterType == typeof(long?)) { long?value = HttpDispatcherUtil.ParseLongOrNull(str); if (!value.HasValue) { failed = true; break; } argValues.Add(value.Value); } else if (argument.ParameterType == typeof(float) || argument.ParameterType == typeof(float?)) { double?value = HttpDispatcherUtil.ParseFloatOrNull(str); if (!value.HasValue) { failed = true; break; } argValues.Add((float)value.Value); } else if (argument.ParameterType == typeof(double) || argument.ParameterType == typeof(double?)) { double?value = HttpDispatcherUtil.ParseDoubleOrNull(str); if (!value.HasValue) { failed = true; break; } argValues.Add(value.Value); } else if (argument.ParameterType == typeof(decimal) || argument.ParameterType == typeof(decimal?)) { decimal?value = HttpDispatcherUtil.ParseDecimalOrNull(str); if (!value.HasValue) { failed = true; break; } argValues.Add(value.Value); } else { throw new ArgumentException($"don't know how to parse arguments of type {argument.ParameterType} after encountering argument {argument.Name} of {handler.Endpoint}"); } } if (failed) { // unmatched argument; try next matcher continue; } if (handler.EndpointAttribute.Method != null && handler.EndpointAttribute.Method != httpMethod) { // endpoint's HTTP method doesn't match request's HTTP method availableMethodsForPath.Add(handler.EndpointAttribute.Method); continue; } // we're ready; dispatch it var eea = new EndpointEventArgs <TContext>(context, handler.Responder, handler.Endpoint); OnCallingEndpoint(eea); if (eea.Responded) { return; } try { handler.Endpoint.Invoke(handler.Responder, argValues.ToArray()); } catch (TargetInvocationException exc) { var reea = new ResponderExceptionEventArgs <TContext>(context, handler.Responder, handler.Endpoint, exc.InnerException); OnResponderException(reea); if (reea.Responded) { return; } SendJson500Exception(context, exc); } return; } // call the unhandled request handler var urea = new UnhandledRequestEventArgs <TContext>(context) { AvailableMethodsForPath = availableMethodsForPath }; OnUnhandledRequest(urea); if (urea.Responded) { return; } // call the default unhandled request handler SendJson404(context); }