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)); }
public void Can_roundtrip_DispatchItem_with_complex_event() { var body = new XDoc("msg").Elem("foo", "bar"); var channel = new XUri("channel://foo.com/bar"); var resource = new XUri("http://foo.com/baz/0"); var origin1 = new XUri("http://foo.com/baz/1"); var origin2 = new XUri("http://foo.com/baz/2"); var recipient1 = new DispatcherRecipient(new XUri("http://recipient1")); var recipient2 = new DispatcherRecipient(new XUri("http://recipient2")); var via1 = new XUri("http://via1"); var via2 = new XUri("http://via2"); var ev = new DispatcherEvent(body, channel, resource, origin1, origin2); ev = ev.WithRecipient(false, recipient1, recipient2).WithVia(via1).WithVia(via2); var item = new DispatchItem( new XUri("http://foo"), ev, "abc" ); var serializer = new DispatchItemSerializer(); var stream = serializer.ToStream(item); var item2 = serializer.FromStream(stream); Assert.AreEqual(item.Uri, item2.Uri, "uri mismatch"); Assert.AreEqual(item.Location, item2.Location, "location mismatch"); Assert.AreEqual(item.Event.Id, item2.Event.Id, "id mismatch"); Assert.AreEqual(body.ToCompactString(), item2.Event.AsDocument().ToCompactString(), "body mismatch"); Assert.AreEqual(channel, item2.Event.Channel, "channel mismatch"); Assert.AreEqual(resource, item2.Event.Resource, "resource mismatch"); Assert.AreEqual(origin1, item2.Event.Origins[0], "first origin mismatch"); Assert.AreEqual(origin2, item2.Event.Origins[1], "second origin mismatch"); Assert.AreEqual(recipient1.Uri, item2.Event.Recipients[0].Uri, "first recipient mismatch"); Assert.AreEqual(recipient2.Uri, item2.Event.Recipients[1].Uri, "second recipient mismatch"); Assert.AreEqual(via1, item2.Event.Via[0], "first via mismatch"); Assert.AreEqual(via2, item2.Event.Via[1], "second via mismatch"); }
public void Deregister(XUri uri) { lock(_registry) { if(!_registry.ContainsKey(uri)) { return; } _registry.Remove(uri); _map.Remove(uri); } }
public void Exact_Match() { XUriMap<string> map = new XUriMap<string>(); string key = "foo/bar"; map[new XUri("test://foo/bar")] = key; string match; int similarity; XUri test = new XUri("test://foo/bar"); map.TryGetValue(test, out match, out similarity); Assert.AreEqual(key, match); Assert.AreEqual(test.MaxSimilarity, similarity); }
//--- Constructors --- public HttpTransport(IDreamEnvironment env, XUri uri, AuthenticationSchemes authenticationSheme) { if(env == null) { throw new ArgumentNullException("env"); } if(uri == null) { throw new ArgumentNullException("uri"); } _env = env; _uri = uri.WithoutCredentialsPathQueryFragment(); _minSimilarity = _uri.MaxSimilarity; _sourceInternal = _uri + " (internal)"; _sourceExternal = _uri.ToString(); _authenticationSheme = authenticationSheme; }
//--- Constructors --- public HttpTransport(IDreamEnvironment env, XUri uri, AuthenticationSchemes authenticationSheme, string dreamInParamAuthtoken) { if(env == null) { throw new ArgumentNullException("env"); } if(uri == null) { throw new ArgumentNullException("uri"); } _env = env; _uri = uri.WithoutCredentialsPathQueryFragment(); _minSimilarity = _uri.MaxSimilarity; _sourceInternal = _uri + " (internal)"; _sourceExternal = _uri.ToString(); _authenticationSheme = authenticationSheme; _dreamInParamAuthtoken = dreamInParamAuthtoken; this.ServerSignature = "Dream-HTTPAPI/" + DreamUtil.DreamVersion; }
//--- Methods --- public int GetScoreWithNormalizedUri(XUri uri, out XUri normalized) { normalized = uri; switch(uri.Scheme.ToLowerInvariant()) { case "http": case "https": return 1; case "ext-http": normalized = normalized.WithScheme("http"); return int.MaxValue; case "ext-https": normalized = normalized.WithScheme("https"); return int.MaxValue; default: return 0; } }
public void Can_roundtrip_DispatchItem() { var msg = new XDoc("msg"); var channel = new XUri("channel://foo.com/bar"); var origin = new XUri("http://foo.com/baz"); var ev = new DispatcherEvent(msg, channel, origin); var item = new DispatchItem( new XUri("http://foo"), ev, "abc" ); var serializer = new DispatchItemSerializer(); var stream = serializer.ToStream(item); var item2 = serializer.FromStream(stream); Assert.AreEqual(item.Uri, item2.Uri, "uri mismatch"); Assert.AreEqual(item.Location, item2.Location, "location mismatch"); Assert.AreEqual(item.Event.Id, item2.Event.Id, "id mismatch"); }
public void Add_via_to_event() { XDoc msg = new XDoc("msg"); XUri via1 = new XUri("http://foo.com/route1"); XUri via2 = new XUri("http://foo.com/route2"); DispatcherEvent ev1 = new DispatcherEvent(msg, new XUri("channel://foo.com/bar"), new XUri("http://foo.com/baz")); DispatcherEvent ev2 = ev1.WithVia(via1); Assert.AreEqual(0, ev1.Via.Length); Assert.AreEqual(1, ev2.Via.Length); Assert.AreEqual(via1, ev2.Via[0]); DispatcherEvent ev3 = ev2.WithVia(via2); Assert.AreEqual(2, ev3.Via.Length); Assert.AreEqual(via1, ev3.Via[0]); Assert.AreEqual(via2, ev3.Via[1]); DreamMessage ev3msg = ev3.AsMessage(); Assert.AreEqual(msg, ev3msg.ToDocument()); Assert.AreEqual(ev1.Id, ev3.Id); Assert.AreEqual("channel://foo.com/bar", ev3msg.Headers.DreamEventChannel); Assert.AreEqual("http://foo.com/baz", ev3msg.Headers.DreamEventOrigin[0]); Assert.AreEqual(via1.ToString(), ev3msg.Headers.DreamEventVia[0]); }
public void Adding_new_sub_will_push_combined_set_to_upstream_subscriber() { var downstream = CreatePubSubService().WithInternalKey().AtLocalHost; var upstreamUri = new XUri("http://upstream/"); var upstreamMock = MockPlug.Register(upstreamUri); XDoc downstreamSet = null; upstreamMock.Expect().Verb("POST").RequestDocument(_ => { downstreamSet = _; return true; }).Response(DreamMessage.Ok()); var subscribeToDownstream = new XDoc("subscription-set") .Elem("uri.owner", upstreamUri) .Start("subscription") .Attr("id", "1") .Elem("channel", "pubsub://*/*") .Start("recipient").Elem("uri", upstreamUri).End() .End(); // subscribe to set updates from downstream, expect most recent version to be pushed var downstreamResponse = downstream.At("subscribers").PostAsync(subscribeToDownstream).Wait(); Assert.IsTrue(downstreamResponse.IsSuccessful, downstreamResponse.ToText()); Assert.IsTrue(upstreamMock.WaitAndVerify(TimeSpan.FromSeconds(10)), upstreamMock.VerificationFailure); // someone else posts a subscription, expect a new push including that sub upstreamMock.Expect().Verb("POST").RequestDocument(_ => { downstreamSet = _; return true; }).Response(DreamMessage.Ok()); var subscription = new XDoc("subscription-set") .Elem("uri.owner", "http://foo/") .Start("subscription") .Attr("id", "1") .Elem("channel", "foo://bar/baz") .Start("recipient").Elem("uri", "http://foo/bar").End() .End(); var subResponse = downstream.At("subscribers").PostAsync(subscription).Wait(); Assert.IsTrue(subResponse.IsSuccessful, subResponse.ToText()); Assert.IsTrue(upstreamMock.WaitAndVerify(TimeSpan.FromSeconds(10)), upstreamMock.VerificationFailure); Assert.AreEqual(1, downstreamSet["subscription[channel='foo://bar/baz']"].ListLength); }
public Yield convert(DreamContext context, DreamMessage request, Result<DreamMessage> response) { string methodStr = context.GetParam("method", string.Empty); string aliasStr = context.GetParam("id", string.Empty); XUri secPage = new XUri( context.ServerUri ).At( "deki", "pages", "=Convert:" + methodStr ); Plug _dekiSec = Plug.New( secPage ); XDoc secDoc = _dekiSec.Get().ToDocument(); string userURL = secDoc["user.author/@href"].AsInnerText; Plug _dekiUser = Plug.New( userURL ); XDoc userDoc = _dekiUser.Get().ToDocument(); string perms = userDoc["permissions.user"]["operations"].AsInnerText; if ( !perms.Contains("UNSAFECONTENT") ) { response.Return( DreamMessage.Forbidden("UNSAFECONTENT not enabled") ); yield break; } XUri codePage = new XUri( context.ServerUri ).At( "deki","pages", "=Convert:" + methodStr,"contents"); Plug _deki = Plug.New( codePage, new TimeSpan(0,0,15) ); string bodyText = _deki.With("format", "xhtml").Get().ToDocument()["body"]["pre"].Contents; for ( int i = 0; i < toHTML.GetLength(0); i++ ) { bodyText = Regex.Replace( bodyText, toHTML[i,0], toHTML[i,1] ); } //string codeStr = HttpUtility.HtmlDecode( bodyText ); //XDoc doc = XDocFactory.From( codeStr, MimeType.ANY ); //response.Return( DreamMessage.Ok( MimeType.TEXT, bodyText ) ); Assembly scriptCode = CompileCode( bodyText, response ); if ( scriptCode != null ) { XmlDocument outDoc = runScript( scriptCode, aliasStr ); response.Return( DreamMessage.Ok( MimeType.XML, new XDoc(outDoc) ) ); } yield break; }
public IEnumerator<IYield> Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) { var match = GetBestMatch(uri); yield return AsyncUtil.Fork(() => match.Invoke(plug, verb, uri, MemorizeAndClone(request), response), new Result(TimeSpan.MaxValue)); }
public void EncodeFragment() { Assert.AreEqual("a^b|c#d", XUri.EncodeFragment("a^b|c#d")); }
public void TestGethashcodeWithNullQueryParam() { XUri uri = new XUri("http://foobar").With("abc", null); int hashcode = uri.GetHashCode(); }
public void TestTryParse() { Assert.IsFalse(XUri.TryParse("htt;//") != null); }
public void EncodeQuery() { Assert.AreEqual("a^b|c", XUri.EncodeQuery("a^b|c")); }
public void Windows_drive_file_path_uri_with_backslashes() { XUri uri = new XUri(@"file:///c:\temp\foo.txt"); Assert.AreEqual(@"file:///c:/temp/foo.txt", uri.ToString()); }
//--- Constructors --- /// <summary> /// Create new handler instance /// </summary> public HttpHandler() { if (_env == null) { lock (SyncRoot) { if (_env == null) { _log.InfoMethodCall("Startup"); try { _log.InfoMethodCall("ctor: initializing HttpHandler"); NameValueCollection settings = System.Configuration.ConfigurationManager.AppSettings; // determine storage locations string basePath = HttpContext.Current.ApplicationInstance.Server.MapPath("~"); string storagePath = settings["storage-dir"] ?? settings["service-dir"]; if (string.IsNullOrEmpty(storagePath)) { storagePath = Path.Combine(basePath, "storage"); } else if (!Path.IsPathRooted(storagePath)) { storagePath = Path.Combine(basePath, storagePath); } // read configuration string apikey = settings["apikey"]; _uri = new XUri(settings["public-uri"] ?? settings["root-uri"] ?? "http://localhost/@api"); _minSimilarity = _uri.MaxSimilarity; // start dreamhost XDoc config = new XDoc("config") .Elem("guid", settings["guid"]) .Elem("uri.public", _uri.ToString()) .Elem("storage-dir", storagePath) .Elem("host-path", settings["host-path"]) .Elem("connect-limit", settings["connect-limit"]) .Elem("apikey", apikey); IDreamEnvironment env = new DreamHostService(); env.Initialize(config); // load assemblies in 'services' folder string servicesFolder = settings["service-dir"] ?? Path.Combine("bin", "services"); if (!Path.IsPathRooted(servicesFolder)) { servicesFolder = Path.Combine(basePath, servicesFolder); } _log.DebugFormat("examining services directory '{0}'", servicesFolder); if (Directory.Exists(servicesFolder)) { Plug host = env.Self.With("apikey", apikey); foreach (string file in Directory.GetFiles(servicesFolder, "*.dll")) { string assembly = Path.GetFileNameWithoutExtension(file); _log.DebugFormat("attempting to load '{0}'", assembly); // register assembly blueprints DreamMessage response = host.At("load").With("name", assembly).Post(new Result <DreamMessage>(TimeSpan.MaxValue)).Wait(); if (!response.IsSuccessful) { _log.WarnFormat("DreamHost: ERROR: assembly '{0}' failed to load", file); } } } else { _log.WarnFormat("DreamHost: WARN: no services directory '{0}'", servicesFolder); } // execute script string scriptFilename = settings["script"]; if (!string.IsNullOrEmpty(scriptFilename)) { string filename = scriptFilename; if (!Path.IsPathRooted(filename)) { filename = Path.Combine(basePath, filename); } // execute xml script file XDoc script = XDocFactory.LoadFrom(filename, MimeType.XML); Plug host = env.Self.With("apikey", apikey); host.At("execute").Post(script); } // register plug factory for this uri Plug.AddEndpoint(this); // set _env variable so other constructors don't initialize it anymore _env = env; } catch (Exception e) { _log.ErrorExceptionMethodCall(e, "ctor"); throw; } } } } }
/// <summary> /// Perform startup configuration of a service instance. /// </summary> /// <remarks> /// Should not be manually invoked and should only be overridden if <see cref="Start(MindTouch.Xml.XDoc,Autofac.IContainer,MindTouch.Tasking.Result)"/> isn't already overriden. /// </remarks> /// <param name="config">Service configuration.</param> /// <param name="result">Synchronization handle for coroutine invocation.</param> /// <returns>Iterator used by <see cref="Coroutine"/> execution environment.</returns> protected virtual Yield Start(XDoc config, Result result) { Result <DreamMessage> res; // store configuration and uri _config = config; _self = Plug.New(config["uri.self"].AsUri); if (_self == null) { throw new ArgumentNullException("uri.self"); } _owner = Plug.New(config["uri.owner"].AsUri); // check for api-key settings _apikey = config["apikey"].AsText; // process 'set-cookie' entries List <DreamCookie> setCookies = DreamCookie.ParseAllSetCookieNodes(config["set-cookie"]); if (setCookies.Count > 0) { Cookies.Update(setCookies, null); } // grant private access key to self, host, and owner //string privateAcccessCookie = HttpUtil.RenderSetCookieHeader(HttpUtil.SetCookie("service-key", PrivateAccessKey, Self.Uri.Path, Self.Uri.Host, DateTime.MaxValue)); //Cookies.Update(HttpUtil.ParseSetCookieHeader(privateAcccessCookie), null); DreamCookie privateAcccessCookie = DreamCookie.NewSetCookie("service-key", PrivateAccessKey, Self.Uri); Cookies.Update(privateAcccessCookie, null); yield return(Env.At("@grants").Post(DreamMessage.Ok(privateAcccessCookie.AsSetCookieDocument), new Result <DreamMessage>(TimeSpan.MaxValue))); if (Owner != null) { yield return(res = Owner.At("@grants").Post(DreamMessage.Ok(privateAcccessCookie.AsSetCookieDocument), new Result <DreamMessage>(TimeSpan.MaxValue))); if (!res.Value.IsSuccessful) { throw new ArgumentException("unexpected failure setting grants on owner service"); } } // check if this service requires a service-license to work if (this is IDreamServiceLicense) { string service_license = config["service-license"].AsText; if (string.IsNullOrEmpty(service_license)) { throw new DreamAbortException(DreamMessage.LicenseRequired("service-license missing")); } // extract public RSA key for validation RSACryptoServiceProvider public_key = RSAUtil.ProviderFrom(GetType().Assembly); if (public_key == null) { throw new DreamAbortException(DreamMessage.InternalError("service assembly invalid")); } // validate the service-license _license = null; Dictionary <string, string> values; try { // parse service-license values = HttpUtil.ParseNameValuePairs(service_license); if (!Encoding.UTF8.GetBytes(service_license.Substring(0, service_license.LastIndexOf(','))).VerifySignature(values["dsig"], public_key)) { throw new DreamAbortException(DreamMessage.InternalError("invalid service-license (1)")); } // check if the SID matches string sid; if (!values.TryGetValue("sid", out sid) || !SID.HasPrefix(XUri.TryParse(sid), true)) { throw new DreamAbortException(DreamMessage.InternalError("invalid service-license (2)")); } _license = service_license; } catch (Exception e) { // unexpected error, blame it on the license if (e is DreamAbortException) { throw; } throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license (1)")); } // validate expiration date string expirationtext; if (values.TryGetValue("expire", out expirationtext)) { try { DateTime expiration = DateTime.Parse(expirationtext); if (expiration < DateTime.UtcNow) { _license = null; } } catch (Exception e) { _license = null; // unexpected error, blame it on the license if (e is DreamAbortException) { throw; } throw new DreamAbortException(DreamMessage.InternalError("corrupt service-license (2)")); } } // check if a license was assigned if (_license == null) { throw new DreamAbortException(DreamMessage.LicenseRequired("service-license has expired")); } } else { config["service-license"].RemoveAll(); } // create built-in services _storage = Plug.New(config["uri.storage"].AsUri); _pubsub = Plug.New(config["uri.pubsub"].AsUri); // done _log.Debug("Start"); result.Return(); }
//--- Class Methods --- /// <summary> /// Merge two subscriptions on matchine channel and resource. /// </summary> /// <param name="channel">Common channel.</param> /// <param name="resource">Common resource.</param> /// <param name="owner">Common owner.</param> /// <param name="cookie">Subscription set cookie.</param> /// <param name="first">First subscription to merge.</param> /// <param name="second">Second subscription to merge.</param> /// <returns></returns> public static PubSubSubscription MergeForChannelAndResource(XUri channel, XUri resource, PubSubSubscriptionSet owner, DreamCookie cookie, PubSubSubscription first, PubSubSubscription second) { return(new PubSubSubscription(channel, resource, owner, cookie, first, second)); }
//--- Methods --- void IHttpHandler.ProcessRequest(HttpContext httpContext) { var key = new object(); DreamMessage request = null; try { string verb = httpContext.Request.HttpMethod; XUri requestUri = HttpUtil.FromHttpContext(httpContext); _env.AddActivityDescription(key, string.Format("Incoming: {0} {1}", verb, requestUri.ToString())); _log.DebugMethodCall("ProcessRequest", verb, requestUri); // create request message request = new DreamMessage(DreamStatus.Ok, new DreamHeaders(httpContext.Request.Headers), MimeType.New(httpContext.Request.ContentType), httpContext.Request.ContentLength, httpContext.Request.InputStream); DreamUtil.PrepareIncomingMessage(request, httpContext.Request.ContentEncoding, string.Format("{0}://{1}{2}", httpContext.Request.Url.Scheme, httpContext.Request.Url.Authority, httpContext.Request.ApplicationPath), httpContext.Request.UserHostAddress, httpContext.Request.UserAgent); // process message Result <DreamMessage> response = _env.SubmitRequestAsync(verb, requestUri, httpContext.User, request, new Result <DreamMessage>(TimeSpan.MaxValue)).Block(); request.Close(); DreamMessage item = response.HasException ? DreamMessage.InternalError(response.Exception) : response.Value; // set status if (_log.IsDebugEnabled) { _log.DebugMethodCall("ProcessRequest[Status]", item.Status, String.Format("{0}{1}", httpContext.Request.Url.GetLeftPart(UriPartial.Authority), httpContext.Request.RawUrl).Replace("/index.aspx", "/")); } httpContext.Response.StatusCode = (int)item.Status; // remove internal headers item.Headers.DreamTransport = null; item.Headers.DreamPublicUri = null; // create stream for response (this will force the creation of the 'Content-Length' header as well) Stream stream = item.ToStream(); // copy headers foreach (KeyValuePair <string, string> pair in item.Headers) { _log.TraceMethodCall("ProcessRequest[Header]", pair.Key, pair.Value); httpContext.Response.AppendHeader(pair.Key, pair.Value); } // add set-cookie headers to response if (item.HasCookies) { foreach (DreamCookie cookie in item.Cookies) { httpContext.Response.AppendHeader(DreamHeaders.SET_COOKIE, cookie.ToSetCookieHeader()); } } // send message stream long size = item.ContentLength; if (((size == -1) || (size > 0)) && (stream != Stream.Null)) { stream.CopyTo(httpContext.Response.OutputStream, size, new Result <long>(TimeSpan.MaxValue)).Wait(); } item.Close(); } catch (Exception ex) { _log.ErrorExceptionMethodCall(ex, "CommonRequestHandler"); if (request != null) { request.Close(); } if (httpContext != null) { httpContext.Response.Close(); } } finally { _env.RemoveActivityDescription(key); } }
/// <summary> /// Create a subscription from a subscription document. /// </summary> /// <param name="sub">Subscription document.</param> /// <param name="owner">Owning set.</param> public PubSubSubscription(XDoc sub, PubSubSubscriptionSet owner) { Owner = owner; // sanity check the input XDoc channels = sub["channel"]; if (channels.IsEmpty) { throw new ArgumentException("<subscription> must have at least one <channel>"); } XDoc filter = sub["filter"]; if (filter.ListLength > 1) { throw new ArgumentException("<subscription> must have zero or one <filter>"); } XDoc proxy = sub["uri.proxy"]; if (proxy.ListLength > 1) { throw new ArgumentException("<subscription> must have zero or one <uri.proxy>"); } XDoc recipients = sub["recipient"]; if (recipients.IsEmpty) { throw new ArgumentException("<subscription> must have at least one valid <recipient>"); } if (recipients.ListLength > 1 && proxy.ListLength == 0) { throw new ArgumentException("<subscription> must include <uri.proxy> if there is more than one <recipient>"); } // create our internal representation try { Id = sub["@id"].Contents; if (string.IsNullOrEmpty(Id)) { Id = Guid.NewGuid().ToString(); } XDoc cookie = sub["set-cookie"]; if (!cookie.IsEmpty) { Cookie = DreamCookie.ParseSetCookie(cookie); } List <XUri> channelList = new List <XUri>(); foreach (XDoc c in channels) { channelList.Add(c.AsUri); } Channels = channelList.ToArray(); List <XUri> resourceList = new List <XUri>(); foreach (XDoc r in sub["uri.resource"]) { resourceList.Add(r.AsUri); } Resources = resourceList.ToArray(); if (proxy.IsEmpty) { Destination = new DispatcherRecipient(recipients).Uri; } else { Destination = proxy.AsUri; _isProxy = true; } List <DispatcherRecipient> recipientList = new List <DispatcherRecipient>(); foreach (XDoc recipient in recipients) { recipientList.Add(new DispatcherRecipient(recipient)); } Recipients = recipientList.ToArray(); } catch (Exception e) { throw new ArgumentException("Unable to parse subscription: " + e.Message, e); } }
private string GetUriTitle(string title) { return(XUri.EncodeSegment(title.ReplaceAll("-", "_", " ", "_"))); }
public DekiScriptLiteral Visit(DekiScriptBinary expr, DekiScriptEnv env) { DekiScriptExpression Left = expr.Left; DekiScriptExpression Right = expr.Right; switch (expr.OpCode) { case DekiScriptBinary.Op.LeftValue: return(Left.VisitWith(this, env)); case DekiScriptBinary.Op.IdentityEqual: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); return(DekiScriptBinary.IdentityEqual(left, right)); } case DekiScriptBinary.Op.IdentityNotEqual: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); return(DekiScriptBinary.IdentityNotEqual(left, right)); } case DekiScriptBinary.Op.IsType: { DekiScriptLiteral left = Left.VisitWith(this, env); string type = ((DekiScriptString)Right).Value; return(DekiScriptBool.New(StringUtil.EqualsInvariantIgnoreCase(type, "any") || StringUtil.EqualsInvariantIgnoreCase(left.ScriptTypeName, type))); } case DekiScriptBinary.Op.Equal: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); return(DekiScriptBinary.Equal(left, right)); } case DekiScriptBinary.Op.NotEqual: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); return(DekiScriptBinary.NotEqual(left, right)); } case DekiScriptBinary.Op.GreaterOrEqual: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); if (DekiScriptLiteral.CoerceValuesToSameType(ref left, ref right)) { switch (left.ScriptType) { case DekiScriptType.BOOL: case DekiScriptType.NUM: return(DekiScriptBool.New(left.AsNumber() >= right.AsNumber())); case DekiScriptType.STR: return(DekiScriptBool.New(StringUtil.CompareInvariant(left.AsString(), right.AsString()) >= 0)); default: return(DekiScriptNil.Value); } } else { return(DekiScriptNil.Value); } } case DekiScriptBinary.Op.GreaterThan: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); if (DekiScriptLiteral.CoerceValuesToSameType(ref left, ref right)) { switch (left.ScriptType) { case DekiScriptType.BOOL: case DekiScriptType.NUM: return(DekiScriptBool.New(left.AsNumber() > right.AsNumber())); case DekiScriptType.STR: return(DekiScriptBool.New(StringUtil.CompareInvariant(left.AsString(), right.AsString()) > 0)); default: return(DekiScriptNil.Value); } } else { return(DekiScriptNil.Value); } } case DekiScriptBinary.Op.LessOrEqual: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); if (DekiScriptLiteral.CoerceValuesToSameType(ref left, ref right)) { switch (left.ScriptType) { case DekiScriptType.BOOL: case DekiScriptType.NUM: return(DekiScriptBool.New(left.AsNumber() <= right.AsNumber())); case DekiScriptType.STR: return(DekiScriptBool.New(StringUtil.CompareInvariant(left.AsString(), right.AsString()) <= 0)); default: return(DekiScriptNil.Value); } } else { return(DekiScriptNil.Value); } } case DekiScriptBinary.Op.LessThan: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); if (DekiScriptLiteral.CoerceValuesToSameType(ref left, ref right)) { switch (left.ScriptType) { case DekiScriptType.BOOL: case DekiScriptType.NUM: return(DekiScriptBool.New(left.AsNumber() < right.AsNumber())); case DekiScriptType.STR: return(DekiScriptBool.New(StringUtil.CompareInvariant(left.AsString(), right.AsString()) < 0)); default: return(DekiScriptNil.Value); } } else { return(DekiScriptNil.Value); } } case DekiScriptBinary.Op.LogicalAnd: { DekiScriptLiteral result = Left.VisitWith(this, env); if (!result.IsNilFalseZero) { result = Right.VisitWith(this, env); } return(result); } case DekiScriptBinary.Op.LogicalOr: { DekiScriptLiteral result = Left.VisitWith(this, env); if (result.IsNilFalseZero) { result = Right.VisitWith(this, env); } return(result); } case DekiScriptBinary.Op.Addition: return(DekiScriptNumber.New(Left.VisitWith(this, env).AsNumber() + Right.VisitWith(this, env).AsNumber())); case DekiScriptBinary.Op.Division: return(DekiScriptNumber.New(Left.VisitWith(this, env).AsNumber() / Right.VisitWith(this, env).AsNumber())); case DekiScriptBinary.Op.Modulo: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); if ((left is DekiScriptString) && ((right is DekiScriptMap) || (right is DekiScriptList))) { // NOTE (steveb): string.format shorthand notation: "abc = $abc" % { abc: 123 } -OR- "0 = $0" % [ 123 ] return(DekiScriptLiteral.FromNativeValue(DekiScriptLibrary.StringFormat(((DekiScriptString)left).Value, right.NativeValue))); } else { return(DekiScriptNumber.New(left.AsNumber() % right.AsNumber())); } } case DekiScriptBinary.Op.Multiplication: return(DekiScriptNumber.New(Left.VisitWith(this, env).AsNumber() * Right.VisitWith(this, env).AsNumber())); case DekiScriptBinary.Op.Subtraction: return(DekiScriptNumber.New(Left.VisitWith(this, env).AsNumber() - Right.VisitWith(this, env).AsNumber())); case DekiScriptBinary.Op.NullCoalesce: { DekiScriptLiteral result = Left.VisitWith(this, env); if (result.IsNil) { result = Right.VisitWith(this, env); } return(result); } case DekiScriptBinary.Op.Concat: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); if (left is DekiScriptNil) { return(right); } else if (right is DekiScriptNil) { return(left); } else if ((left is DekiScriptMap) && (right is DekiScriptMap)) { // left and right expressions are maps, merge them DekiScriptMap result = new DekiScriptMap(); result.AddRange((DekiScriptMap)left); result.AddRange((DekiScriptMap)right); return(result); } else if ((left is DekiScriptList) && (right is DekiScriptList)) { // left and right expressions are lists, concatenate them DekiScriptList result = new DekiScriptList(); result.AddRange((DekiScriptList)left); result.AddRange((DekiScriptList)right); return(result); } else { // treat left and right expressions as strings string leftText = left.AsString(); string rightText = right.AsString(); if ((leftText != null) && (rightText != null)) { return(DekiScriptString.New(leftText + rightText)); } else if (leftText != null) { return(DekiScriptString.New(leftText)); } else if (rightText != null) { return(DekiScriptString.New(rightText)); } else { return(DekiScriptNil.Value); } } } case DekiScriptBinary.Op.UriAppend: { // TODO (steveb): we should throw an exception when the LHS is not a valid string or uri XUri left = XUri.TryParse(Left.VisitWith(this, env).AsString()); string result = null; if (left != null) { DekiScriptLiteral right = Right.VisitWith(this, env); if (right is DekiScriptString) { result = DekiScriptLibrary.UriBuild(left, right.AsString(), null); } else if (right is DekiScriptMap) { result = DekiScriptLibrary.UriBuild(left, null, (Hashtable)right.NativeValue); } else { result = left.ToString(); } } return(DekiScriptLiteral.FromNativeValue(result)); } case DekiScriptBinary.Op.InCollection: { DekiScriptLiteral left = Left.VisitWith(this, env); DekiScriptLiteral right = Right.VisitWith(this, env); if (right is DekiScriptList) { foreach (DekiScriptLiteral item in ((DekiScriptList)right).Value) { if (!DekiScriptBinary.Equal(left, item).IsNilFalseZero) { return(DekiScriptBool.True); } } return(DekiScriptBool.False); } else if (right is DekiScriptMap) { foreach (DekiScriptLiteral item in ((DekiScriptMap)right).Value.Values) { if (!DekiScriptBinary.Equal(left, item).IsNilFalseZero) { return(DekiScriptBool.True); } } return(DekiScriptBool.False); } else { return(DekiScriptBool.False); } } } throw new InvalidOperationException("invalid op code:" + expr.OpCode); }
//--- Class Methods --- public static void Main(string[] args) { var console = Console.Error; console.WriteLine("MindTouch CSV2CB - Import CSV files into Couchbase"); console.WriteLine(); // parse command line options string password = null; XUri host = null; string doctype = null; bool help = false; string select = null; var options = new OptionSet { { "host=", "Couchbase hostname with bucket name.\nExample: http://example.com:8091/bucket", v => host = XUri.TryParse(v) }, { "password="******"(optional) Password for Couchbase bucket.", v => password = v }, { "doctype=", "(optional) Document type identifier (doctype) to add to each converted JSON document.", v => doctype = v }, { "select=", "(optional) List of CSV columns to import. By default, all columns are imported.", v => select = v }, { "h|?|help", "This help text", v => help = (v != null) } }; var filenames = options.Parse(args); // show help if requested if (help) { WriteOptions(Console.Out, options); return; } // validate arguments if (host == null) { console.WriteLine("ERROR: missing couchbase hostname"); console.WriteLine(); WriteOptions(Console.Out, options); return; } HashSet <string> columns = null; if (select != null) { try { CsvTable schema = null; using (var reader = new StringReader(select)) { schema = CsvTable.NewFromStream(reader); } columns = new HashSet <string>(); foreach (var column in schema.Headers) { columns.Add(column); } } catch (Exception e) { console.WriteLine("ERROR: {0}", e.Message); return; } } // create client and verify connection try { _client = CreateClient(host, password); var key = "test:" + StringUtil.CreateAlphaNumericKey(16); if (!_client.Store(StoreMode.Set, key, "succcess!")) { throw new ApplicationException("unable to connect to couchbase server"); } _client.Remove(key); } catch (Exception e) { console.WriteLine("ERROR: {0}", e.Message); return; } // process all files var loadStopwatch = new Stopwatch(); var convertStopwatch = new Stopwatch(); var importStopwatch = new Stopwatch(); var documentTotal = 0; var importFailedTotal = 0; try { foreach (var filename in filenames) { if (!File.Exists(filename)) { console.WriteLine("ERROR: unable to find '{0}'", filename); return; } try { // load CSV file console.Write("Loading file '{0}'...", filename); loadStopwatch.Start(); var table = CsvTable.NewFromPath(filename, Encoding.UTF8); loadStopwatch.Stop(); console.WriteLine("done ({0:#,##0} rows)", table.RowCount); // converting from CSV to JSON documents console.Write("Converting rows..."); var documents = new List <KeyValuePair <string, string> >(); convertStopwatch.Start(); foreach (var row in table) { var value = RowToJson(columns, row, doctype); if (value == null) { continue; } var key = StringUtil.CreateAlphaNumericKey(16); if (!string.IsNullOrEmpty(doctype)) { key = doctype + ":" + key; } documents.Add(new KeyValuePair <string, string>(key, value)); } convertStopwatch.Stop(); documentTotal += documents.Count; console.WriteLine("done ({0:#,##0} documents)", documents.Count); // importing JSON documents if (documents.Any()) { console.Write("Importing documents..."); int importFailed; importStopwatch.Start(); Send(documents, out importFailed); importStopwatch.Stop(); importFailedTotal += importFailed; console.WriteLine("done ({0:#,##0} documents)", documents.Count - importFailed); } } catch (Exception e) { console.WriteLine("ERROR: error loading file '{0}': {1}", filename, e.Message); return; } } } finally { loadStopwatch.Stop(); convertStopwatch.Stop(); importStopwatch.Stop(); var loadTime = loadStopwatch.Elapsed.TotalSeconds; var convertTime = convertStopwatch.Elapsed.TotalSeconds; var importTime = importStopwatch.Elapsed.TotalSeconds; console.WriteLine(); console.WriteLine("{0:#,##0.000} seconds elapsed (loading: {1:#,##0.000}s, converting: {2:#,##0.000}s, importing: {3:#,##0.000}s)", loadTime + convertTime + importTime, loadTime, convertTime, importTime); console.WriteLine("{0:#,##0} records loaded ({1:#,##0.000} records/second)", documentTotal, documentTotal / loadTime); console.WriteLine("{0:#,##0} records converted ({1:#,##0.000} records/second)", documentTotal, documentTotal / convertTime); console.WriteLine("{0:#,##0} records imported ({1:#,##0.000} records/second)", documentTotal - importFailedTotal, (documentTotal - importFailedTotal) / importTime); if (importFailedTotal > 0) { console.WriteLine("WARNING: {0:#,##0} records failed to import!", importFailedTotal); } } }
public DreamMessage SyncUri(XUri uri) { return(Response(new XDoc("r").Elem("uri", uri.WithoutQuery()))); }
public void Subscribing_to_pubsub_channel_results_in_combined_set_being_pushed() { var downstream = CreatePubSubService().WithInternalKey().AtLocalHost; var upstreamUri = new XUri("http://upstream/"); var upstreamMock = MockPlug.Register(upstreamUri); XDoc downstreamSet = null; upstreamMock.Expect().Verb("POST").RequestDocument(_ => { downstreamSet = _; return true; }).Response(DreamMessage.Ok()); var subscribeToDownstream = new XDoc("subscription-set") .Elem("uri.owner", upstreamUri) .Start("subscription") .Attr("id", "1") .Elem("channel", "foo://bar/baz/*") .Start("recipient").Elem("uri", upstreamUri).End() .End() .Start("subscription") .Attr("id", "1") .Elem("channel", "pubsub://*/*") .Start("recipient").Elem("uri", upstreamUri).End() .End(); // subscribe to set updates from downstream, expect most recent version to be pushed var downstreamResponse = downstream.At("subscribers").PostAsync(subscribeToDownstream).Wait(); var location = downstreamResponse.Headers.Location; Assert.IsTrue(downstreamResponse.IsSuccessful, downstreamResponse.ToText()); Assert.IsTrue(upstreamMock.WaitAndVerify(TimeSpan.FromSeconds(10)), upstreamMock.VerificationFailure); Assert.AreEqual(1, downstreamSet["subscription[channel='foo://bar/baz/*']"].ListLength); subscribeToDownstream .Start("subscription") .Attr("id", "3") .Elem("channel", "foo://bar/bob") .Start("recipient").Elem("uri", upstreamUri).End() .End(); // change subscription, expect most recent version to be pushed upstreamMock.Expect().Verb("POST").RequestDocument(_ => { downstreamSet = _; return true; }).Response(DreamMessage.Ok()); downstreamResponse = Plug.New(location).PutAsync(subscribeToDownstream).Wait(); Assert.IsTrue(downstreamResponse.IsSuccessful, downstreamResponse.ToText()); Assert.IsTrue(upstreamMock.WaitAndVerify(TimeSpan.FromSeconds(10)), upstreamMock.VerificationFailure); Assert.AreEqual(1, downstreamSet["subscription[channel='foo://bar/baz/*']"].ListLength); Assert.AreEqual(1, downstreamSet["subscription[channel='foo://bar/bob']"].ListLength); }
private Yield HandleInvoke(Action <string> activity, Plug plug, string verb, XUri uri, DreamMessage request, Result <DreamMessage> response) { Result <IAsyncResult> async; // remove internal headers request.Headers.DreamTransport = null; // set request headers request.Headers.Host = uri.Host; if (request.Headers.UserAgent == null) { request.Headers.UserAgent = "Dream/" + DreamUtil.DreamVersion; } // add cookies to request if (request.HasCookies) { request.Headers[DreamHeaders.COOKIE] = DreamCookie.RenderCookieHeader(request.Cookies); } // check if we can pool the request with an existing one if ((plug.Credentials == null) && StringUtil.ContainsInvariantIgnoreCase(verb, "GET")) { // create the request hashcode StringBuilder buffer = new StringBuilder(); buffer.AppendLine(uri.ToString()); foreach (KeyValuePair <string, string> header in request.Headers) { buffer.Append(header.Key).Append(": ").Append(header.Value).AppendLine(); } Guid hash = new Guid(StringUtil.ComputeHash(buffer.ToString())); // check if an active connection exists Result <DreamMessage> relay = null; lock (_requests) { List <Result <DreamMessage> > pending; if (_requests.TryGetValue(hash, out pending)) { relay = new Result <DreamMessage>(response.Timeout); pending.Add(relay); } else { pending = new List <Result <DreamMessage> >(); pending.Add(response); _requests[hash] = pending; } } // check if we're pooling a request if (relay != null) { // wait for the relayed response yield return(relay); response.Return(relay); yield break; } else { // NOTE (steveb): we use TaskEnv.Instantaneous so that we don't exit the current stack frame before we've executed the continuation; // otherwise, we'll trigger an exception because our result object may not be set. // create new handler to multicast the response to the relays response = new Result <DreamMessage>(response.Timeout, TaskEnv.Instantaneous); response.WhenDone(_ => { List <Result <DreamMessage> > pending; lock (_requests) { _requests.TryGetValue(hash, out pending); _requests.Remove(hash); } // this check should never fail! if (response.HasException) { // send the exception to all relays foreach (Result <DreamMessage> result in pending) { result.Throw(response.Exception); } } else { DreamMessage original = response.Value; // only memorize the message if it needs to be cloned if (pending.Count > 1) { // clone the message to all relays foreach (Result <DreamMessage> result in pending) { result.Return(original.Clone()); } } else { // relay the original message pending[0].Return(original); } } }); } } // initialize request activity("pre WebRequest.Create"); var httpRequest = (HttpWebRequest)WebRequest.Create(uri.ToUri()); activity("post WebRequest.Create"); httpRequest.Method = verb; httpRequest.Timeout = System.Threading.Timeout.Infinite; httpRequest.ReadWriteTimeout = System.Threading.Timeout.Infinite; // Note (arnec): httpRequest AutoRedirect is disabled because Plug is responsible for it (this allows redirects to follow // the appropriate handler instead staying stuck in http end point land httpRequest.AllowAutoRedirect = false; // Note from http://support.microsoft.com/kb/904262 // The HTTP request is made up of the following parts: // 1. Sending the request is covered by using the HttpWebRequest.Timeout method. // 2. Getting the response header is covered by using the HttpWebRequest.Timeout method. // 3. Reading the body of the response is not covered by using the HttpWebResponse.Timeout method. In ASP.NET 1.1 and in later versions, reading the body of the response // is covered by using the HttpWebRequest.ReadWriteTimeout method. The HttpWebRequest.ReadWriteTimeout method is used to handle cases where the response headers are // retrieved in a timely manner but where the reading of the response body times out. httpRequest.KeepAlive = false; httpRequest.ProtocolVersion = System.Net.HttpVersion.Version10; // TODO (steveb): set default proxy //httpRequest.Proxy = WebProxy.GetDefaultProxy(); //httpRequest.Proxy.Credentials = CredentialCache.DefaultCredentials; // set credentials if (plug.Credentials != null) { httpRequest.Credentials = plug.Credentials; httpRequest.PreAuthenticate = true; } else if (!string.IsNullOrEmpty(uri.User) || !string.IsNullOrEmpty(uri.Password)) { httpRequest.Credentials = new NetworkCredential(uri.User ?? string.Empty, uri.Password ?? string.Empty); httpRequest.PreAuthenticate = true; // Note (arnec): this manually adds the basic auth header, so it can authorize // in a single request without requiring challenge var authbytes = Encoding.ASCII.GetBytes(string.Concat(uri.User ?? string.Empty, ":", uri.Password ?? string.Empty)); var base64 = Convert.ToBase64String(authbytes); httpRequest.Headers.Add(DreamHeaders.AUTHORIZATION, "Basic " + base64); } // add request headres foreach (KeyValuePair <string, string> header in request.Headers) { HttpUtil.AddHeader(httpRequest, header.Key, header.Value); } // send message stream if ((request.ContentLength != 0) || (verb == Verb.POST)) { async = new Result <IAsyncResult>(); try { activity("pre BeginGetRequestStream"); httpRequest.BeginGetRequestStream(async.Return, null); activity("post BeginGetRequestStream"); } catch (Exception e) { activity("pre HandleResponse 1"); if (!HandleResponse(activity, e, null, response)) { _log.ErrorExceptionMethodCall(e, "HandleInvoke@BeginGetRequestStream", verb, uri); try { httpRequest.Abort(); } catch { } } yield break; } activity("pre yield BeginGetRequestStream"); yield return(async.Catch()); activity("post yield BeginGetRequestStream"); // send request Stream outStream; try { activity("pre EndGetRequestStream"); outStream = httpRequest.EndGetRequestStream(async.Value); activity("pre EndGetRequestStream"); } catch (Exception e) { activity("pre HandleResponse 2"); if (!HandleResponse(activity, e, null, response)) { _log.ErrorExceptionMethodCall(e, "HandleInvoke@EndGetRequestStream", verb, uri); try { httpRequest.Abort(); } catch { } } yield break; } // copy data using (outStream) { Result <long> res; activity("pre yield CopyStream"); yield return(res = request.ToStream().CopyTo(outStream, request.ContentLength, new Result <long>(TimeSpan.MaxValue)).Catch()); activity("post yield CopyStream"); if (res.HasException) { activity("pre HandleResponse 3"); if (!HandleResponse(activity, res.Exception, null, response)) { _log.ErrorExceptionMethodCall(res.Exception, "*****@*****.**", verb, uri); try { httpRequest.Abort(); } catch { } } yield break; } } } request = null; // wait for response async = new Result <IAsyncResult>(response.Timeout); try { activity("pre BeginGetResponse"); httpRequest.BeginGetResponse(async.Return, null); activity("post BeginGetResponse"); } catch (Exception e) { activity("pre HandleResponse 4"); if (!HandleResponse(activity, e, null, response)) { _log.ErrorExceptionMethodCall(e, "HandleInvoke@BeginGetResponse", verb, uri); try { httpRequest.Abort(); } catch { } } yield break; } activity("pre yield BeginGetResponse"); yield return(async.Catch()); activity("post yield BeginGetResponse"); // check if an error occurred if (async.HasException) { activity("pre HandleResponse 5"); if (!HandleResponse(activity, async.Exception, null, response)) { _log.ErrorExceptionMethodCall(async.Exception, "HandleInvoke@BeginGetResponse", verb, uri); try { httpRequest.Abort(); } catch { } } yield break; } else { // handle response try { HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(async.Value); activity("pre HandleResponse 6"); if (!HandleResponse(activity, null, httpResponse, response)) { try { httpRequest.Abort(); } catch { } } } catch (Exception e) { activity("pre HandleResponse 7"); if (!HandleResponse(activity, e, null, response)) { _log.ErrorExceptionMethodCall(e, "HandleInvoke@EndGetResponse", verb, uri); try { httpRequest.Abort(); } catch { } } yield break; } } }
public void PubSub_downstream_chaining_and_subscription_propagation() { XUri downstreamUri = new XUri("http://localhost/downstream"); var mock = MockPlug.Register(downstreamUri); XDoc downstreamDoc = null; mock.Expect().Verb("GET").Uri(downstreamUri).Response(DreamMessage.Ok(new XDoc("subscription-set") .Elem("uri.owner", downstreamUri) .Start("subscription") .Attr("id", "1") .Elem("channel", "channel:///foo/*") .Elem("uri.proxy", downstreamUri.At("publish")) .Start("recipient").Elem("uri", "http:///foo/sub1").End() .End())); mock.Expect().Verb("POST").Uri(downstreamUri).RequestDocument(doc => { downstreamDoc = doc; return true; }); // create service, which should subscribe to the upstream one Plug upstreamPubSub = CreatePubSubService(new XDoc("config").Start("downstream").Elem("uri", downstreamUri).End()).WithInternalKey().AtLocalHost; Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(10)), mock.VerificationFailure); var subUri = downstreamDoc["subscription/recipient/uri"].AsUri.AsPublicUri(); Plug.GlobalCookies.Update(DreamCookie.ParseAllSetCookieNodes(downstreamDoc["subscription/set-cookie"]), subUri); Assert.AreEqual("pubsub://*/*", downstreamDoc["subscription/channel"].AsText); Assert.AreEqual(upstreamPubSub.Uri.WithoutQuery(), downstreamDoc["uri.owner"].AsUri); Assert.AreEqual(upstreamPubSub.Uri.At("subscribers").WithoutQuery(), subUri.WithoutLastSegment()); // check that our set is properly represented by the upstream service DreamMessage upstreamSet = upstreamPubSub.At("subscribers").GetAsync().Wait(); Assert.IsTrue(upstreamSet.IsSuccessful); XDoc upstreamDoc = upstreamSet.ToDocument(); Assert.AreEqual(1, upstreamDoc["subscription"].ListLength); Assert.AreEqual("channel:///foo/*", upstreamDoc["subscription/channel"].AsText); // update the subscription set on the upstream service XDoc set2 = new XDoc("subscription-set") .Elem("uri.owner", downstreamUri) .Start("subscription") .Attr("id", "1") .Elem("channel", "channel:///bar/*") .Elem("uri.proxy", downstreamUri.At("publish")) .Start("recipient").Elem("uri", "http:///foo/sub1").End() .End(); DreamMessage subPush = Plug.New(subUri).PostAsync(set2).Wait(); Assert.IsTrue(subPush.IsSuccessful); upstreamSet = upstreamPubSub.At("subscribers").GetAsync().Wait(); Assert.IsTrue(upstreamSet.IsSuccessful); upstreamDoc = upstreamSet.ToDocument(); Assert.AreEqual(1, upstreamDoc["subscription"].ListLength); Assert.AreEqual("channel:///bar/*", upstreamDoc["subscription/channel"].AsText); }
//--- Interface Methods --- int IPlugEndpoint.GetScoreWithNormalizedUri(XUri uri, out XUri normalized) { normalized = uri; int similarity = uri.Similarity(_uri); return (similarity >= _minSimilarity) ? similarity : 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); } } // 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; } }
public void Shutdown() { _log.InfoMethodCall("Shutdown", _uri); Plug.RemoveEndpoint(this); _uri = null; // BUGBUGBUG (arnec): the following line may throw an exception on shutdown and // there is no way of differentiating it from other failures, so we log just in case. try { _listener.Stop(); } catch(Exception e) { _log.Debug("Shutdown", e); } }
public void Windows_network_file_path_uri_with_backslashes() { XUri uri = new XUri(@"file:///\\deki-hayes\drive"); Assert.AreEqual("file://///deki-hayes/drive", uri.ToString()); }
/// <summary> /// Create a new subscription set from a subscription set document. /// </summary> /// <param name="setDoc">Set Xml document.</param> /// <param name="location">location id.</param> /// <param name="accessKey">secret key for accessing the set.</param> public PubSubSubscriptionSet(XDoc setDoc, string location, string accessKey) { try { // Note: not using AsUri to avoid automatic local:// translation Owner = new XUri(setDoc["uri.owner"].AsText); MaxFailureDuration = (setDoc["@max-failure-duration"].AsDouble ?? 0).Seconds(); var subscriptions = new List<PubSubSubscription>(); foreach(XDoc sub in setDoc["subscription"]) { subscriptions.Add(new PubSubSubscription(sub, this)); } Version = setDoc["@version"].AsLong; Subscriptions = subscriptions.ToArray(); Location = location; AccessKey = accessKey; MaxFailures = UsesFailureDuration ? int.MaxValue : setDoc["@max-failures"].AsInt ?? MAX_FAILURES; } catch(Exception e) { throw new ArgumentException("Unable to parse subscription set: " + e.Message, e); } }
public void TestToStringFalse() { XUri uri = new XUri("http://*****:*****@hostname/path"); Assert.AreEqual("http://*****:*****@hostname/path", uri.ToString(false), "ToString(false)"); }
//--- Constructors --- internal MockPlugInvocation(string verb, XUri uri, DreamMessage request, DreamHeaders responseHeaders) { Verb = verb; Uri = uri; Request = request; ResponseHeaders = responseHeaders; }
public void TestAppendPath5() { XUri uri = new XUri("http://www.dummy.com:8081/first/second?query=arg"); uri = uri.At("foo/bar"); }
public void Can_mock_a_request_with_a_stream_body() { var tmp = Path.GetTempFileName(); var payload = "blahblah"; File.WriteAllText(tmp, payload); var message = DreamMessage.FromFile(tmp); var uri = new XUri("http://mock/post/stream"); MockPlug.Setup(uri).Verb("POST") .WithMessage(m => m.ToText() == payload) .ExpectAtLeastOneCall(); var response = Plug.New(uri).Post(message, new Result<DreamMessage>()).Wait(); response.AssertSuccess(); MockPlug.VerifyAll(1.Seconds()); }
private MockPlug.IMockInvokee GetBestMatch(XUri uri) { MockPlug.IMockInvokee invokee; // using _registry as our guard for both _map and _registry, since they are always modified in sync lock(_registry) { int result; _map.TryGetValue(uri, out invokee, out result); } if(invokee != null) { return invokee; } return uri.SchemeHostPort.EqualsInvariant(DEFAULT) ? DefaultInvokee : null; }
public void Register_twice_throws() { XUri uri = new XUri("http://www.mindtouch.com/foo"); MockPlug.Register(uri, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { r2.Return(DreamMessage.Ok()); }); try { MockPlug.Register(uri, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { r2.Return(DreamMessage.Ok()); }); } catch(ArgumentException) { return; } catch(Exception e) { Assert.Fail("wrong exception: " + e); } Assert.Fail("no exception`"); }
private void ExecuteRequest(String operation, String url) { DreamMessage msg = null; XUri uri = null; try { uri = new XUri(url); // exectue the specified request and display the results switch (operation.ToUpper()) { case "DELETE": { Plug p = Plug.New(url).WithCredentials(loginTextBox.Text, passwordTextBox.Text); msg = p.DeleteAsync(GetDreamMessage(uri)).Wait(); SetRequestResult(msg, uri); break; } case "GET": { Plug p = Plug.New(url).WithCredentials(loginTextBox.Text, passwordTextBox.Text); msg = DreamMessage.Ok(); msg.Cookies.AddRange(_cookies.Fetch(uri)); msg = p.GetAsync(msg).Wait(); SetRequestResult(msg, uri); break; } case "HEAD": { Plug p = Plug.New(url).WithCredentials(loginTextBox.Text, passwordTextBox.Text); msg = p.InvokeAsync("HEAD", DreamMessage.Ok()).Wait(); if (DreamStatus.Ok == msg.Status) { StringBuilder result = new StringBuilder(); foreach (KeyValuePair <string, string> header in msg.Headers) { result.Append(header.Key); result.Append("="); result.Append(header.Value); result.Append(Environment.NewLine); } msg = DreamMessage.Ok(MimeType.TEXT, result.ToString()); } SetRequestResult(msg, uri); break; } case "POST": { Plug p = Plug.New(url).WithCredentials(loginTextBox.Text, passwordTextBox.Text); msg = p.PostAsync(GetDreamMessage(uri)).Wait(); SetRequestResult(msg, uri); break; } case "PUT": { Plug p = Plug.New(url).WithCredentials(loginTextBox.Text, passwordTextBox.Text); msg = p.PutAsync(GetDreamMessage(uri)).Wait(); SetRequestResult(msg, uri); break; } case "OPTIONS": { Plug p = Plug.New(url).WithCredentials(loginTextBox.Text, passwordTextBox.Text); msg = p.OptionsAsync().Wait(); SetRequestResult(msg, uri); break; } } } catch (DreamResponseException error) { SetRequestResult(error.Response, uri); } catch (Exception error) { SetRequestResult(DreamMessage.Ok(MimeType.TEXT, error.ToString()), uri); } }
/// <summary> /// No-op hook for retrieving a service license string from its Service Identifier uri. /// </summary> /// <param name="sid">Service Identifier.</param> /// <returns>Service license.</returns> protected virtual string TryGetServiceLicense(XUri sid) { return(null); }
Yield IPlugEndpoint.Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result<DreamMessage> response) { _env.UpdateInfoMessage(_sourceInternal, null); Result<DreamMessage> res = new Result<DreamMessage>(response.Timeout); _env.SubmitRequestAsync(verb, uri, null, request, res); yield return res; response.Return(res); }
public IEnumerator <IYield> Invoke(Plug plug, string verb, XUri uri, DreamMessage request, Result <DreamMessage> response) { var match = GetBestMatch(uri); yield return(Async.Fork(() => match.Invoke(plug, verb, uri, MemorizeAndClone(request), response), new Result(TimeSpan.MaxValue))); }
public void Get_via_internal_routing_and_AutoRedirect_off_shows_302() { using(var hostInfo = DreamTestHelper.CreateRandomPortHost()) { var mock = MockService.CreateMockService(hostInfo); var redirectCalled = 0; var redirectUri = new XUri("mock://foo/bar"); mock.Service.CatchAllCallback = delegate(DreamContext context, DreamMessage request, Result<DreamMessage> response) { var msg = "nothing here"; if(context.Uri.LastSegment == "redirect") { _log.Debug("called redirect"); redirectCalled++; response.Return(DreamMessage.Redirect(redirectUri)); return; } _log.DebugFormat("called uri: {0} => {1}", context.Uri, msg); response.Return(DreamMessage.NotFound(msg)); }; var uri = mock.AtLocalMachine.At("redirect"); _log.DebugFormat("calling redirect service at {0}", uri); var r = Plug.New(uri).WithHeader("h", "y").WithoutAutoRedirects().GetAsync().Wait(); Assert.AreEqual(DreamStatus.Found, r.Status, r.HasDocument ? r.ToDocument()["message"].AsText : "request failed: " + r.Status); Assert.AreEqual(1, redirectCalled, "redirect called incorrectly"); Assert.AreEqual(redirectUri.ToString(), r.Headers.Location.ToString()); } }
public void Title_Case02_WithNamespacePrefix_CorrectPathTitle() { // Case 02 // Old path: Namespace:aaa // Old title: Namespace:aaa // move?title=bbb // New path: Namespace:bbb // New title: bbb // Log in as ADMIN Plug p = Utils.BuildPlugForAdmin(); // Run this test for each namespace for (int i = 0; i < name_space.Length; i++) { string path = name_space[i] + Utils.GenerateUniqueName(); PageUtils.SavePage(p, path, name_space[i] + "test"); // Rename page from Namespace:aaa -> bbb using "title" string title = Utils.GenerateUniqueName(); string newtitle = title; string newpath = name_space[i] + title; DreamMessage msg = PageUtils.MovePage(Utils.BuildPlugForAdmin().At("pages", "=" + XUri.DoubleEncode(path), "move").With("title", newtitle)); Assert.IsTrue(msg.IsSuccessful, "move page failed"); Assert.AreEqual(1, msg.ToDocument()["@count"].AsInt, "unexpected number of pages moved"); if (msg.ToDocument()["page/path/@type"].AsText == "fixed") { // fixed path page are not moved, just the title is changed newpath = msg.ToDocument()["page/path"].AsText; } // Retrieve the page and verify correct path/title msg = PageUtils.GetPage(p, newpath); string metapath = msg.ToDocument()["path"].AsText ?? String.Empty; string metatitle = msg.ToDocument()["title"].AsText ?? String.Empty; // path should be Namespace:bbb, title should be bbb, page should be linked Assert.AreEqual(newpath, metapath, "Unexpected path"); Assert.AreEqual(newtitle, metatitle, "Unexpected title"); PageUtils.IsLinked(msg); // Delete page as to not contaminate the namespace PageUtils.DeletePageByName(p, newpath, true); } }
//--- Constructors --- /// <summary> /// Create a new subscription set. /// </summary> /// <param name="owner">Owner uri.</param> /// <param name="version">Version serial number.</param> /// <param name="cookie">Pub sub location access cookie.</param> /// <param name="childSubscriptions">Subscriptions.</param> public PubSubSubscriptionSet(XUri owner, long version, DreamCookie cookie, params PubSubSubscription[] childSubscriptions) { Owner = owner; Version = version; Dictionary<string, PubSubSubscription> subs = new Dictionary<string, PubSubSubscription>(); foreach(var sub in childSubscriptions) { foreach(var channel in sub.Channels) { if(channel.Scheme == "pubsub") { // pubsub scheme is for PubSubService internal use only, so it should never be aggregated continue; } XUri[] resources = (sub.Resources == null || sub.Resources.Length == 0) ? new XUri[] { null } : sub.Resources; foreach(XUri resource in resources) { PubSubSubscription combo; string key = channel + ":" + resource; subs.TryGetValue(key, out combo); subs[key] = PubSubSubscription.MergeForChannelAndResource(channel, resource, this, cookie, sub, combo); } } } Subscriptions = new PubSubSubscription[subs.Count]; subs.Values.CopyTo(Subscriptions, 0); MaxFailures = MAX_FAILURES; }
public static string DoubleUrlEncode(string url) { return(XUri.DoubleEncodeSegment(url)); }
public DreamMessage SyncUri(XUri uri) { return Response(new XDoc("r").Elem("uri", uri.WithoutQuery())); }
public static string DoubleUrlDecode(string url) { return(XUri.DoubleDecode(url)); }
public void Deregister_allows_reregister_of_uri() { XUri uri = new XUri("http://www.mindtouch.com/foo"); int firstCalled = 0; MockPlug.Register(uri, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { firstCalled++; r2.Return(DreamMessage.Ok()); }); Assert.IsTrue(Plug.New(uri).GetAsync().Wait().IsSuccessful); Assert.AreEqual(1, firstCalled); MockPlug.Deregister(uri); int secondCalled = 0; MockPlug.Register(uri, delegate(Plug p, string v, XUri u, DreamMessage r, Result<DreamMessage> r2) { secondCalled++; r2.Return(DreamMessage.Ok()); }); Assert.IsTrue(Plug.New(uri).GetAsync().Wait().IsSuccessful); Assert.AreEqual(1, firstCalled); Assert.AreEqual(1, secondCalled); }
/// <summary> /// Try to get the best matching parent uri. /// </summary> /// <param name="key">Uri to match.</param> /// <param name="value">When the method returns <see langword="True"/>, this variable contains the reference object for matched parent Uri.</param> /// <returns><see langword="True"/> if a match was found.</returns> public bool TryGetValue(XUri key, out T value) { int similarity; return(TryGetValue(key, out value, out similarity)); }
public void Returns_callback_gets_request_data() { var doc = new XDoc("doc").Elem("foo", StringUtil.CreateAlphaNumericKey(6)); var success = new XDoc("yay"); var uri = new XUri("http://mock/foo/").With("foo", "baz"); MockPlug.Setup(new XUri("http://mock/foo")).Returns(invocation => { if(invocation.Verb != "POST") { return DreamMessage.BadRequest("wrong verb: " + invocation.Verb); } if(invocation.Uri != uri) { return DreamMessage.BadRequest("wrong uri: " + invocation.Uri); } if(invocation.Request.Headers["header"] != "value") { return DreamMessage.BadRequest("wrong header value"); } if(invocation.Request.ToDocument() != doc) { return DreamMessage.BadRequest("wrong body"); } return DreamMessage.Ok(success); }); var msg = Plug.New(uri).WithHeader("header", "value").Post(doc, new Result<DreamMessage>()).Wait(); Assert.IsTrue(msg.IsSuccessful, msg.ToDocument().ToPrettyString()); Assert.AreEqual(success, msg.ToDocument()); }
/// <summary> /// Add a new entry to the map. /// </summary> /// <param name="key">Key Uri.</param> /// <param name="value">Reference object.</param> public void Add(XUri key, T value) { Add(key, value, true); }
public void CombinedSet_of_service_combines_all_registered_subs() { XUri c1 = new XUri("channel:///c1"); XUri c2 = new XUri("channel:///c2"); XUri c3 = new XUri("channel:///c3"); XUri r1 = new XUri("http:///r1"); XUri r2 = new XUri("http:///r2"); XDoc set1 = new XDoc("subscription-set") .Attr("max-failures", 1) .Elem("uri.owner", "http:///owner1") .Start("subscription") .Attr("id", "123") .Elem("channel", c1) .Elem("channel", c2) .Elem("uri.proxy", "http:///proxy") .Start("recipient").Attr("auth-token", "abc").Elem("uri", r1).End() .EndAll(); XDoc set2 = new XDoc("subscription-set") .Attr("max-failures", 1) .Elem("uri.owner", "http:///owner2") .Start("subscription") .Attr("id", "123") .Elem("channel", c1) .Elem("channel", c3) .Elem("uri.proxy", "http:///proxy") .Start("recipient").Attr("auth-token", "abc").Elem("uri", r2).End() .EndAll(); Plug pubsub = CreatePubSubService().WithInternalKey().AtLocalHost; DreamMessage response = pubsub.At("subscribers").PostAsync(set1).Wait(); Assert.IsTrue(response.IsSuccessful); Assert.AreEqual(DreamStatus.Created, response.Status); response = pubsub.At("subscribers").PostAsync(set2).Wait(); Assert.IsTrue(response.IsSuccessful); Assert.AreEqual(DreamStatus.Created, response.Status); Thread.Sleep(1000); response = pubsub.At("subscribers").GetAsync().Wait(); Assert.IsTrue(response.IsSuccessful); Assert.AreEqual(DreamStatus.Ok, response.Status); PubSubSubscriptionSet combinedSet = new PubSubSubscriptionSet(response.ToDocument(), "abc", "def"); Assert.AreEqual(3, combinedSet.Subscriptions.Length); XUri owner = pubsub.Uri.WithoutQuery(); foreach(PubSubSubscription subx in combinedSet.Subscriptions) { switch(subx.Channels[0].ToString()) { case "channel:///c1": Assert.AreEqual(owner.At("publish"), subx.Destination); Assert.AreEqual(1, subx.Channels.Length); Assert.AreEqual(c1, subx.Channels[0]); Assert.AreEqual(2, subx.Recipients.Length); bool foundR1 = false; bool foundR2 = false; foreach(DispatcherRecipient r in subx.Recipients) { if(r.Uri == r1) { foundR1 = true; } else if(r.Uri == r2) { foundR2 = true; } } Assert.IsTrue(foundR1 && foundR2); break; case "channel:///c2": Assert.AreEqual(owner.At("publish"), subx.Destination); Assert.AreEqual(1, subx.Channels.Length); Assert.AreEqual(c2, subx.Channels[0]); Assert.AreEqual(1, subx.Recipients.Length); Assert.AreEqual(r1, subx.Recipients[0].Uri); break; case "channel:///c3": Assert.AreEqual(owner.At("publish"), subx.Destination); Assert.AreEqual(1, subx.Channels.Length); Assert.AreEqual(c3, subx.Channels[0]); Assert.AreEqual(1, subx.Recipients.Length); Assert.AreEqual(r2, subx.Recipients[0].Uri); break; default: Assert.Fail(); break; } } }
public XUri Blend( [DekiExtParam("image uri")] XUri image ) { return(Process(image, "-size 500x500 - -matte -virtual-pixel transparent -channel A -blur 0x8 -evaluate subtract 50% -evaluate multiply 2.001")); }
public void Parallel_chaining_subscription_and_message_propagation() { var rootPubsub = Plug.New(_hostInfo.Host.LocalMachineUri.At("host", "$pubsub", "subscribers")); var goTrigger = new ManualResetEvent(false); var pubsubResults = new List<Result<Plug>>(); for(var i = 0; i < 10; i++) { pubsubResults.Add(Async.ForkThread(() => { goTrigger.WaitOne(); return CreatePubSubService("upstream", new XDoc("config").Start("downstream").Elem("uri", rootPubsub).End()).WithInternalKey().AtLocalHost; }, new Result<Plug>())); } var subscriberResults = new List<Result<Tuplet<XUri, AutoMockPlug>>>(); for(var i = 0; i < 20; i++) { var mockUri = new XUri("http://mock/" + i); subscriberResults.Add(Async.ForkThread(() => { goTrigger.WaitOne(); rootPubsub.With("apikey", _hostInfo.ApiKey).Post(new XDoc("subscription-set") .Elem("uri.owner", mockUri) .Start("subscription") .Attr("id", "1") .Elem("channel", "channel://foo/bar") .Start("recipient").Elem("uri", mockUri).End() .End()); var mock = MockPlug.Register(mockUri); return new Tuplet<XUri, AutoMockPlug>(mockUri, mock); }, new Result<Tuplet<XUri, AutoMockPlug>>())); } goTrigger.Set(); var pubsubs = new List<Plug>(); foreach(var r in pubsubResults) { pubsubs.Add(r.Wait()); } var endpoints = new List<XUri>(); var mocks = new List<AutoMockPlug>(); foreach(var r in subscriberResults) { var v = r.Wait(); endpoints.Add(v.Item1); mocks.Add(v.Item2); } foreach(var pubsub in pubsubs) { Plug plug = pubsub; Wait.For(() => { var set = plug.At("subscribers").Get(); return set.ToDocument()["subscription/recipient"].ListLength == endpoints.Count; }, TimeSpan.FromSeconds(10)); } var ev = new DispatcherEvent(new XDoc("blah"), new XUri("channel://foo/bar"), new XUri("http://foobar.com/some/page")); foreach(var mock in mocks) { mock.Expect().Verb("POST").RequestDocument(ev.AsDocument()).Response(DreamMessage.Ok()); } pubsubs[0].At("publish").Post(ev.AsMessage()); foreach(var mock in mocks) { Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(10)), mock.VerificationFailure); } }
public XUri Flip( [DekiExtParam("image uri")] XUri image ) { return(Process(image, "-size 500x500 - -flip")); }
public void Can_aggregate_from_multiple_dream_hosts() { // set up hosts _log.DebugFormat("---- creating upstream hosts"); var sourceHost1 = DreamTestHelper.CreateRandomPortHost(); var source1PubSub = Plug.New(sourceHost1.LocalHost.At("host", "$pubsub").With("apikey", sourceHost1.ApiKey)); var sourceHost2 = DreamTestHelper.CreateRandomPortHost(); var source2PubSub = Plug.New(sourceHost2.LocalHost.At("host", "$pubsub").With("apikey", sourceHost2.ApiKey)); // create aggregator _log.DebugFormat("---- creating downstream host"); var aggregatorPath = "pubsubaggregator"; var aggregatorHost = DreamTestHelper.CreateRandomPortHost(); aggregatorHost.Host.RunScripts(new XDoc("config") .Start("script").Start("action") .Attr("verb", "POST") .Attr("path", "/host/services") .Start("config") .Elem("path", aggregatorPath) .Elem("sid", "sid://mindtouch.com/dream/2008/10/pubsub") .Elem("apikey", "abc") .Start("upstream") .Elem("uri", source1PubSub.At("subscribers")) .Elem("uri", source2PubSub.At("subscribers")) .End() .End().End(), null); var aggregatorPubSub = aggregatorHost.LocalHost.At(aggregatorPath).With("apikey", "abc"); // create subscription _log.DebugFormat("---- create downstream subscription"); var testUri = new XUri("http://mock/aggregator"); var serviceKey = "1234"; var accessCookie = DreamCookie.NewSetCookie("service-key", serviceKey, testUri); var subscriberApiKey = "xyz"; var set = new XDoc("subscription-set") .Elem("uri.owner", "http:///owner1") .Start("subscription") .Attr("id", "1") .Add(accessCookie.AsSetCookieDocument) .Elem("channel", "channel:///foo/*") .Start("recipient") .Attr("authtoken", subscriberApiKey) .Elem("uri", testUri) .End() .End(); var r = aggregatorPubSub.At("subscribers").PostAsync(set).Wait(); Assert.IsTrue(r.IsSuccessful, r.Status.ToString()); Assert.AreEqual(DreamStatus.Created, r.Status); // Verify that upstream host pubsub services have the subscription Func<DreamMessage, bool> waitFunc = response => { var sub = response.ToDocument()["subscription-set/subscription[channel='channel:///foo/*']"]; return (!sub.IsEmpty && sub["recipient/uri"].AsText.EqualsInvariantIgnoreCase(testUri.ToString()) && sub["recipient/@authtoken"].AsText.EqualsInvariant(subscriberApiKey)); }; Assert.IsTrue(WaitFor(source1PubSub.At("diagnostics", "subscriptions"), waitFunc, TimeSpan.FromSeconds(5)), "source 1 didn't get the subscription"); Assert.IsTrue(WaitFor(source2PubSub.At("diagnostics", "subscriptions"), waitFunc, TimeSpan.FromSeconds(5)), "source 2 didn't get the subscription"); // set up destination mock DispatcherEvent aggregatorEvent = new DispatcherEvent( new XDoc("aggregator"), new XUri("channel:///foo/bar"), new XUri("http://foobar.com/some/page")); DispatcherEvent source1Event = new DispatcherEvent( new XDoc("source1"), new XUri("channel:///foo/bar"), new XUri("http://foobar.com/some/page")); DispatcherEvent source2Event = new DispatcherEvent( new XDoc("source2"), new XUri("channel:///foo/bar"), new XUri("http://foobar.com/some/page")); var mock = MockPlug.Register(testUri); // Publish event into aggregator mock.Expect().Verb("POST").RequestDocument(aggregatorEvent.AsDocument()); r = aggregatorPubSub.At("publish").PostAsync(aggregatorEvent.AsMessage()).Wait(); Assert.IsTrue(r.IsSuccessful, r.Status.ToString()); Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(10)), mock.VerificationFailure); // Publish event into source1 mock.Reset(); mock.Expect().Verb("POST").RequestDocument(source1Event.AsDocument()); r = source1PubSub.At("publish").PostAsync(source1Event.AsMessage()).Wait(); Assert.IsTrue(r.IsSuccessful, r.Status.ToString()); Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(10)), mock.VerificationFailure); // Publish event into source2 mock.Reset(); mock.Expect().Verb("POST").RequestDocument(source2Event.AsDocument()); r = source2PubSub.At("publish").PostAsync(source2Event.AsMessage()).Wait(); Assert.IsTrue(r.IsSuccessful, r.Status.ToString()); Assert.IsTrue(mock.WaitAndVerify(TimeSpan.FromSeconds(10)), mock.VerificationFailure); }
public void EncodeSegment() { Assert.AreEqual("a^b", XUri.EncodeSegment("a^b")); }