Exemplo n.º 1
0
 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);
     }
 }
Exemplo n.º 2
0
 // 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);
     }
 }
Exemplo n.º 3
0
        private void AddDefaultView(Router.Dest dest)
        {
            string controllerName = dest.controllerClass.Name;

            if (controllerName.EndsWith("Controller"))
            {
                controllerName = Sharpen.Runtime.Substring(controllerName, 0, controllerName.Length
                                                           - 10);
            }
            dest.defaultViewClass = Find <View>(dest.controllerClass.Assembly.GetName(), StringHelper.Join
                                                    (controllerName + "View"));
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
 /// <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);
     }
 }
Exemplo n.º 6
0
        // 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));
        }
Exemplo n.º 7
0
 internal static bool IsGoodMatch(Router.Dest dest, string path)
 {
     if (Slash.CountIn(dest.prefix) > 1)
     {
         return(true);
     }
     // We want to match (/foo, :a) for /foo/bar/blah and (/, :a) for /123
     // but NOT / for /foo or (/, :a) for /foo or /foo/ because default route
     // (FooController#index) for /foo and /foo/ takes precedence.
     if (dest.prefix.Length == 1)
     {
         return(dest.pathParams.Count > 0 && !MaybeController(path));
     }
     return(dest.pathParams.Count > 0 || (path.EndsWith("/") && Slash.CountIn(path) ==
                                          2));
 }
Exemplo n.º 8
0
        internal static bool PrefixMatches(Router.Dest dest, string path)
        {
            Log.Debug("checking prefix {}{} for path: {}", new object[] { dest.prefix, dest.pathParams
                                                                          , path });
            if (!path.StartsWith(dest.prefix))
            {
                return(false);
            }
            int prefixLen = dest.prefix.Length;

            if (prefixLen > 1 && path.Length > prefixLen && path[prefixLen] != '/')
            {
                return(false);
            }
            // prefix is / or prefix is path or prefix/...
            return(true);
        }
Exemplo n.º 9
0
 // /path/foo/bar with /path/:arg1/:arg2 will set {arg1=>foo, arg2=>bar}
 private void SetMoreParams(Controller.RequestContext rc, string pathInfo, Router.Dest
                            dest)
 {
     Preconditions.CheckState(pathInfo.StartsWith(dest.prefix), "prefix should match");
     if (dest.pathParams.Count == 0 || dest.prefix.Length == pathInfo.Length)
     {
         return;
     }
     string[] parts = Iterables.ToArray <string>(WebApp.pathSplitter.Split(Sharpen.Runtime.Substring
                                                                               (pathInfo, dest.prefix.Length)));
     Log.Debug("parts={}, params={}", parts, dest.pathParams);
     for (int i = 0; i < dest.pathParams.Count && i < parts.Length; ++i)
     {
         string key = dest.pathParams[i];
         if (key[0] == ':')
         {
             rc.MoreParams()[Sharpen.Runtime.Substring(key, 1)] = parts[i];
         }
     }
 }
Exemplo n.º 10
0
        /// <exception cref="Javax.Servlet.ServletException"/>
        /// <exception cref="System.IO.IOException"/>
        protected override void Service(HttpServletRequest req, HttpServletResponse res)
        {
            res.SetCharacterEncoding("UTF-8");
            string uri = HtmlQuoting.QuoteHtmlChars(req.GetRequestURI());

            if (uri == null)
            {
                uri = "/";
            }
            if (devMode && uri.Equals("/__stop"))
            {
                // quick hack to restart servers in dev mode without OS commands
                res.SetStatus(res.ScNoContent);
                Log.Info("dev mode restart requested");
                PrepareToExit();
                return;
            }
            // if they provide a redirectPath go there instead of going to
            // "/" so that filters can differentiate the webapps.
            if (uri.Equals("/"))
            {
                string redirectPath = webApp.GetRedirectPath();
                if (redirectPath != null && !redirectPath.IsEmpty())
                {
                    res.SendRedirect(redirectPath);
                    return;
                }
            }
            string method = req.GetMethod();

            if (method.Equals("OPTIONS"))
            {
                DoOptions(req, res);
                return;
            }
            if (method.Equals("TRACE"))
            {
                DoTrace(req, res);
                return;
            }
            if (method.Equals("HEAD"))
            {
                DoGet(req, res);
                // default to bad request
                return;
            }
            string pathInfo = req.GetPathInfo();

            if (pathInfo == null)
            {
                pathInfo = "/";
            }
            Controller.RequestContext rc = injector.GetInstance <Controller.RequestContext>();
            if (SetCookieParams(rc, req) > 0)
            {
                Cookie ec = rc.Cookies()[ErrorCookie];
                if (ec != null)
                {
                    rc.SetStatus(System.Convert.ToInt32(rc.Cookies()[StatusCookie].GetValue()));
                    RemoveErrorCookies(res, uri);
                    rc.Set(Params.ErrorDetails, ec.GetValue());
                    Render(typeof(ErrorPage));
                    return;
                }
            }
            rc.prefix = webApp.Name();
            Router.Dest dest = null;
            try
            {
                dest = router.Resolve(method, pathInfo);
            }
            catch (WebAppException e)
            {
                rc.error = e;
                if (!e.Message.Contains("not found"))
                {
                    rc.SetStatus(res.ScInternalServerError);
                    Render(typeof(ErrorPage));
                    return;
                }
            }
            if (dest == null)
            {
                rc.SetStatus(res.ScNotFound);
                Render(typeof(ErrorPage));
                return;
            }
            rc.devMode = devMode;
            SetMoreParams(rc, pathInfo, dest);
            Controller controller = injector.GetInstance(dest.controllerClass);

            try
            {
                // TODO: support args converted from /path/:arg1/...
                dest.action.Invoke(controller, (object[])null);
                if (!rc.rendered)
                {
                    if (dest.defaultViewClass != null)
                    {
                        Render(dest.defaultViewClass);
                    }
                    else
                    {
                        if (rc.status == 200)
                        {
                            throw new InvalidOperationException("No view rendered for 200");
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("error handling URI: " + uri, e);
                // Page could be half rendered (but still not flushed). So redirect.
                RedirectToErrorPage(res, e, uri, devMode);
            }
        }
Exemplo n.º 11
0
 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)));
 }