Example #1
0
 public void Can_roundtrip_AtPath_via_GetRelativePathTo_with_trailing_slash_on_base()
 {
     var relative = "b/c";
     var baseUri = new XUri("http://foo/a/");
     var combined = baseUri.AtPath(relative);
     Assert.AreEqual(relative, combined.GetRelativePathTo(baseUri));
 }
Example #2
0
        public void Can_roundtrip_GetRelativePathTo_via_AtPath_with_trailing_slash_on_uri()
        {
            var uri       = new XUri("http://foo/a/b/c/");
            var baseUri   = new XUri("http://foo/a");
            var relative  = uri.GetRelativePathTo(baseUri);
            var roundtrip = baseUri.AtPath(relative);

            Assert.AreEqual(uri.ToString(), roundtrip.ToString());
        }
        public static string UriBuild(
            [DekiScriptParam("base uri")] XUri uri,
            [DekiScriptParam("path segments to append (must a string or list of strings)", true)] object path,
            [DekiScriptParam("query parameters to append", true)] Hashtable args
            )
        {
            if (path is string)
            {
                uri = uri.AtPath((string)path);
            }
            else if (path is ArrayList)
            {
                foreach (string segment in (ArrayList)path)
                {
                    uri = uri.At(XUri.EncodeSegment(segment));
                }
            }
            if (args != null)
            {
                foreach (DictionaryEntry entry in args)
                {
                    string key = (string)entry.Key;

                    // remove existing parameter
                    uri = uri.WithoutParams(key);

                    // check if entry is a list of values
                    if (entry.Value is ArrayList)
                    {
                        foreach (var value in (ArrayList)entry.Value)
                        {
                            uri = uri.With(key, SysUtil.ChangeType <string>(value));
                        }
                    }
                    else if (entry.Value != null)
                    {
                        uri = uri.With(key, SysUtil.ChangeType <string>(entry.Value));
                    }
                }
            }
            return(uri.ToString());
        }
Example #4
0
 public void TestAppendPath4()
 {
     XUri uri = new XUri("http://www.dummy.com:8081/first/second?query=arg");
     uri = uri.AtPath("foo/bar?q=a");
     Assert.AreEqual("http://www.dummy.com:8081/first/second/foo/bar?query=arg&q=a", uri.ToString());
 }
Example #5
0
 public void TestAppendPath2()
 {
     XUri uri = new XUri("http://www.dummy.com:8081/first/second");
     uri = uri.AtPath("/foo/bar");
     Assert.AreEqual("http://www.dummy.com:8081/first/second//foo/bar", uri.ToString());
 }
Example #6
0
 public void Can_roundtrip_GetRelativePathTo_via_AtPath_with_trailing_slash_on_uri()
 {
     var uri = new XUri("http://foo/a/b/c/");
     var baseUri = new XUri("http://foo/a");
     var relative = uri.GetRelativePathTo(baseUri);
     var roundtrip = baseUri.AtPath(relative);
     Assert.AreEqual(uri.ToString(), roundtrip.ToString());
 }
Example #7
0
        private DekiScriptInvocationTargetDescriptor ConvertFunction(XDoc function)
        {
            string functionName = function["name"].AsText;

            if (string.IsNullOrEmpty(functionName))
            {
                _log.WarnFormat("function without name in script {0}; skipping function definition", _manifestUri);
                return(null);
            }

            // determine function access level
            DreamAccess access;

            switch (function["access"].AsText ?? "public")
            {
            case "private":
                access = DreamAccess.Private;
                break;

            case "internal":
                access = DreamAccess.Internal;
                break;

            case "public":
                access = DreamAccess.Public;
                break;

            default:
                _log.WarnFormat("unrecognized access level '{0}' for function {1} in script {2}; defaulting to public", function["access"].AsText, functionName, _manifestUri);
                access = DreamAccess.Public;
                break;
            }

            // convert parameters
            List <DekiScriptParameter> parameters = new List <DekiScriptParameter>();

            foreach (XDoc param in function["param"])
            {
                string paramName = param["@name"].AsText;

                // determine if parameter has a default value
                string            paramDefault           = param["@default"].AsText;
                DekiScriptLiteral paramDefaultExpression = DekiScriptNil.Value;
                bool paramOptional = false;
                if (paramDefault != null)
                {
                    paramOptional = true;
                    try {
                        paramDefaultExpression = ScriptRuntime.Evaluate(DekiScriptParser.Parse(Location.Start, paramDefault), DekiScriptEvalMode.Evaluate, ScriptRuntime.CreateEnv());
                    } catch (Exception e) {
                        _log.ErrorExceptionFormat(e, "invalid default value for parameter {0} in function {1} in script {2}; skipping function definition", paramName, functionName, _manifestUri);
                        return(null);
                    }
                }
                else
                {
                    paramOptional = (param["@optional"].AsText == "true");
                }

                // determine parameter type
                string         paramType = param["@type"].AsText ?? "any";
                DekiScriptType paramScriptType;
                if (!SysUtil.TryParseEnum(paramType, out paramScriptType))
                {
                    _log.WarnFormat("unrecognized param type '{0}' for parameter {1} in function {2} in script {3}; defaulting to any", paramType, paramName, functionName, _manifestUri);
                    paramScriptType = DekiScriptType.ANY;
                }

                // add parameter
                parameters.Add(new DekiScriptParameter(paramName, paramScriptType, paramOptional, param.Contents, typeof(object), paramDefaultExpression));
            }
            var parameterArray = parameters.ToArray();

            // determine function body
            XDoc   ret  = function["return"];
            string src  = ret["@src"].AsText;
            string type = ret["@type"].AsText;
            DekiScriptExpression expression;

            if (!string.IsNullOrEmpty(src))
            {
                // 'src' attribute is set, load the script from it
                XDoc script;
                if (_manifestUri != null)
                {
                    // check if uri is relative
                    XUri scriptUri = XUri.TryParse(src) ?? _manifestUri.AtPath(src);
                    script = Plug.New(scriptUri).Get().ToDocument();
                }
                else
                {
                    // check if filename is relative
                    if (!Path.IsPathRooted(src))
                    {
                        src = Path.Combine(_resourcesPath, src);
                    }
                    script = XDocFactory.LoadFrom(src, MimeType.XML);
                }
                expression = DekiScriptParser.Parse(script);
                type       = type ?? "xml";
            }
            else if (!ret["html"].IsEmpty)
            {
                // <return> element contains a <html> node; parse it as a script
                expression = DekiScriptParser.Parse(ret["html"]);
                type       = type ?? "xml";
            }
            else if (!ret.IsEmpty)
            {
                // <return> element contains something else; use the text contents as deki-script expression
                var location = new Location(string.Format("/function[name={0}]/return", functionName));
                expression = DekiScriptParser.Parse(location, function["return"].AsText ?? string.Empty);
                expression = DekiScriptExpression.ReturnScope(location, expression);
                type       = type ?? "any";
            }
            else
            {
                _log.WarnFormat("function {0} has no body in script {1}; skipping function definition", functionName, _manifestUri);
                return(null);
            }

            // determine return type
            DekiScriptType returnScriptType;

            if (!SysUtil.TryParseEnum(type, out returnScriptType))
            {
                _log.WarnFormat("unrecognized return type '{0}' for function {1} in script {2}; defaulting to any", type, functionName, _manifestUri);
                returnScriptType = DekiScriptType.ANY;
            }

            // create function descriptor
            var    target      = new DekiScriptScriptFunctionInvocationTarget(access, parameterArray, expression, _commonEnv, returnScriptType);
            string description = function["description"].AsText;
            string transform   = function["@transform"].AsText;

            return(new DekiScriptInvocationTargetDescriptor(access, false, false, functionName, parameterArray, returnScriptType, description, transform, target));
        }
Example #8
0
        /// <summary>
        /// Create a new host with provided configuration and an Inversion of Control container.
        /// </summary>
        /// <remarks>
        /// The IoC container is also injected into default activator, so that <see cref="IDreamService"/> instances
        /// can be resolved from the container. The host configuration is provided to the container as a typed parameter.
        /// </remarks>
        /// <param name="config">Host configuration.</param>
        /// <param name="container">IoC Container.</param>
        public DreamHost(XDoc config, IContainer container)
        {
            if (config == null)
            {
                throw new ArgumentNullException("config");
            }

            // read host settings
            string appDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0].FullyQualifiedName);
            int    limit        = config["connect-limit"].AsInt ?? 0;
            int    httpPort     = config["http-port"].AsInt ?? DEFAULT_PORT;
            AuthenticationSchemes authenticationScheme = AuthenticationSchemes.Anonymous;
            string authShemes = config["authentication-shemes"].AsText;

            if (!String.IsNullOrEmpty(authShemes))
            {
                try {
                    authenticationScheme = (AuthenticationSchemes)Enum.Parse(typeof(AuthenticationSchemes), authShemes, true);
                } catch (Exception e) {
                    _log.Warn(String.Format("invalid authetication scheme specified :{0}", authShemes), e);
                }
            }

            // get the authtoken for whitelisting dream.in.* query args
            _dreamInParamAuthtoken = config["dream.in.authtoken"].AsText;
            if (!string.IsNullOrEmpty(_dreamInParamAuthtoken))
            {
                _log.Debug("Host is configured in dream.in param authorizing mode");
            }

            // read ip-addresses
            var addresses = new List <string>();

            foreach (XDoc ip in config["host|ip"])
            {
                addresses.Add(ip.AsText);
            }
            if (addresses.Count == 0)
            {
                // if no addresses were supplied listen to all
                addresses.Add("*:" + httpPort);
            }

            // use default servername
            XUri publicUri = config["uri.public"].AsUri;

            if (publicUri == null)
            {
                // backwards compatibility
                publicUri = config["server-name"].AsUri;
                if (publicUri == null)
                {
                    foreach (IPAddress addr in Dns.GetHostAddresses(Dns.GetHostName()))
                    {
                        if (addr.AddressFamily == AddressFamily.InterNetwork)
                        {
                            XUri.TryParse("http://" + addr, out publicUri);
                        }
                    }
                    if (publicUri == null)
                    {
                        // failed to get an address out of dns, fall back to localhost
                        XUri.TryParse("http://localhost", out publicUri);
                    }
                }
                publicUri = publicUri.AtPath(config["server-path"].AsText ?? config["path-prefix"].AsText ?? string.Empty);
            }

            // create environment and initialize it
            _env = new DreamHostService(container);
            try {
                // initialize environment
                string apikey        = config["apikey"].AsText ?? StringUtil.CreateAlphaNumericKey(32);
                XDoc   serviceConfig = new XDoc("config");
                var    storageType   = config["storage/@type"].AsText ?? "local";
                if ("s3".EqualsInvariant(storageType))
                {
                    serviceConfig.Add(config["storage"]);
                }
                else
                {
                    serviceConfig.Elem("storage-dir", config["storage-dir"].AsText ?? config["service-dir"].AsText ?? appDirectory);
                }
                serviceConfig.Elem("apikey", apikey);
                serviceConfig.Elem("uri.public", publicUri);
                serviceConfig.Elem("connect-limit", limit);
                serviceConfig.Elem("guid", config["guid"].AsText);
                serviceConfig.AddAll(config["components"]);
                var memorize = config["memorize-aliases"];
                if (!memorize.IsEmpty)
                {
                    serviceConfig.Elem("memorize-aliases", memorize.AsBool);
                }
                _env.Initialize(serviceConfig);

                // initialize host plug
                _host = _env.Self.With("apikey", apikey);

                // load assemblies in 'services' folder
                string servicesFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "services");
                if (Directory.Exists(servicesFolder))
                {
                    // Note (arnec): Deprecated, but the suggested alternative really doesn't apply since we don't want to
                    // load services into a separate appdomain.
#pragma warning disable 618,612
                    AppDomain.CurrentDomain.AppendPrivatePath("services");
#pragma warning restore 618,612
                    foreach (string file in Directory.GetFiles(servicesFolder, "*.dll"))
                    {
                        // register assembly blueprints
                        DreamMessage response = _host.At("load").With("name", Path.GetFileNameWithoutExtension(file)).Post(new Result <DreamMessage>(TimeSpan.MaxValue)).Wait();
                        if (!response.IsSuccessful)
                        {
                            _log.WarnFormat("DreamHost: ERROR: assembly '{0}' failed to load", file);
                        }
                    }
                }

                // add acccess-points
                AddListener(new XUri(String.Format("http://{0}:{1}/", "localhost", httpPort)), authenticationScheme);

                // check if user prescribed a set of IP addresses to use
                if (addresses != null)
                {
                    // listen to custom addresses (don't use the supplied port info, we expect that to be part of the address)
                    foreach (string address in addresses)
                    {
                        if (!StringUtil.EqualsInvariantIgnoreCase(address, "localhost"))
                        {
                            AddListener(new XUri(String.Format("http://{0}/", address)), authenticationScheme);
                        }
                    }
                }
                else
                {
                    // add listeners for all known IP addresses
                    foreach (IPAddress address in Dns.GetHostAddresses(Dns.GetHostName()))
                    {
                        XUri uri = MakeUri(address, httpPort);
                        if (uri != null)
                        {
                            AddListener(uri, authenticationScheme);
                            try {
                                foreach (string alias in Dns.GetHostEntry(address).Aliases)
                                {
                                    AddListener(new XUri(String.Format("http://{0}:{1}/", alias, httpPort)), authenticationScheme);
                                }
                            } catch { }
                        }
                    }
                }
            } catch (Exception e) {
                if ((e is HttpListenerException) && e.Message.EqualsInvariant("Access is denied"))
                {
                    _log.ErrorExceptionMethodCall(e, "ctor", "insufficient privileges to create HttpListener, make sure the application runs with Administrator rights");
                }
                else
                {
                    _log.ErrorExceptionMethodCall(e, "ctor");
                }
                try {
                    _env.Deinitialize();
                } catch { }
                throw;
            }
        }