private Router.Dest AddController(WebApp.HTTP httpMethod, string path, Type cls, string action, IList <string> names) { try { // Look for the method in all public methods declared in the class // or inherited by the class. // Note: this does not distinguish methods with the same signature // but different return types. // TODO: We may want to deal with methods that take parameters in the future MethodInfo method = cls.GetMethod(action, null); Router.Dest dest = routes[path]; if (dest == null) { // avoid any runtime checks dest = new Router.Dest(path, method, cls, names, httpMethod); routes[path] = dest; return(dest); } dest.methods.AddItem(httpMethod); return(dest); } catch (MissingMethodException) { throw new WebAppException(action + "() not found in " + cls); } catch (SecurityException) { throw new WebAppException("Security exception thrown for " + action + "() in " + cls); } }
/// <summary>Setup of a webapp serving route.</summary> /// <param name="method">the http method for the route</param> /// <param name="pathSpec">the path spec in the form of /controller/action/:args etc. /// </param> /// <param name="cls">the controller class</param> /// <param name="action">the controller method</param> public virtual void Route(WebApp.HTTP method, string pathSpec, Type cls, string action ) { IList <string> res = ParseRoute(pathSpec); router.Add(method, res[RPath], cls, action, res.SubList(RParams, res.Count)); }
internal Dest(string path, MethodInfo method, Type cls, IList <string> pathParams, WebApp.HTTP httpMethod) { prefix = Preconditions.CheckNotNull(path); action = Preconditions.CheckNotNull(method); controllerClass = Preconditions.CheckNotNull(cls); this.pathParams = pathParams != null?ImmutableList.CopyOf(pathParams) : EmptyList; methods = EnumSet.Of(httpMethod); }
// starting point to look for default classes // path->dest /// <summary>Add a route to the router.</summary> /// <remarks> /// Add a route to the router. /// e.g., add(GET, "/foo/show", FooController.class, "show", [name...]); /// The name list is from /foo/show/:name/... /// </remarks> internal virtual Router.Dest Add(WebApp.HTTP httpMethod, string path, Type cls, string action, IList <string> names) { lock (this) { Log.Debug("adding {}({})->{}#{}", new object[] { path, names, cls, action }); Router.Dest dest = AddController(httpMethod, path, cls, action, names); AddDefaultView(dest); return(dest); } }
private Router.Dest LookupRoute(WebApp.HTTP method, string path) { string key = path; do { Router.Dest dest = routes[key]; if (dest != null && MethodAllowed(method, dest)) { if ((object)key == path) { // shut up warnings Log.Debug("exact match for {}: {}", key, dest.action); return(dest); } else { if (IsGoodMatch(dest, path)) { Log.Debug("prefix match2 for {}: {}", key, dest.action); return(dest); } } return(ResolveAction(method, dest, path)); } KeyValuePair <string, Router.Dest> lower = routes.LowerEntry(key); if (lower == null) { return(null); } dest = lower.Value; if (PrefixMatches(dest, path)) { if (MethodAllowed(method, dest)) { if (IsGoodMatch(dest, path)) { Log.Debug("prefix match for {}: {}", lower.Key, dest.action); return(dest); } return(ResolveAction(method, dest, path)); } // check other candidates int slashPos = key.LastIndexOf('/'); key = slashPos > 0 ? Sharpen.Runtime.Substring(path, 0, slashPos) : "/"; } else { key = "/"; } }while (true); }
/// <summary>Resolve a path to a destination.</summary> internal virtual Router.Dest Resolve(string httpMethod, string path) { lock (this) { WebApp.HTTP method = WebApp.HTTP.ValueOf(httpMethod); // can throw Router.Dest dest = LookupRoute(method, path); if (dest == null) { return(ResolveDefault(method, path)); } return(dest); } }
// Dest may contain a candidate controller private Router.Dest ResolveAction(WebApp.HTTP method, Router.Dest dest, string path ) { if (dest.prefix.Length == 1) { return(null); } Preconditions.CheckState(!IsGoodMatch(dest, path), dest.prefix); Preconditions.CheckState(Slash.CountIn(path) > 1, path); IList <string> parts = WebApp.ParseRoute(path); string controller = parts[WebApp.RController]; string action = parts[WebApp.RAction]; return(Add(method, StringHelper.Pjoin(string.Empty, controller, action), dest.controllerClass , action, null)); }
// Assume /controller/action style path private Router.Dest ResolveDefault(WebApp.HTTP method, string path) { IList <string> parts = WebApp.ParseRoute(path); string controller = parts[WebApp.RController]; string action = parts[WebApp.RAction]; // NameController is encouraged default Type cls = Find <Controller>(StringHelper.Join(controller, "Controller")); if (cls == null) { cls = Find <Controller>(controller); } if (cls == null) { throw new WebAppException(StringHelper.Join(path, ": controller for ", controller , " not found")); } return(Add(method, DefaultPrefix(controller, action), cls, action, null)); }
internal static bool MethodAllowed(WebApp.HTTP method, Router.Dest dest) { // Accept all methods by default, unless explicity configured otherwise. return(dest.methods.Contains(method) || (dest.methods.Count == 1 && dest.methods. Contains(WebApp.HTTP.Get))); }