Beispiel #1
0
        //--- Class Methods ---

        /// <summary>
        /// Retrieve user credentials from a request uri and/or headers.
        /// </summary>
        /// <param name="uri">Request uri.</param>
        /// <param name="headers">Request headers.</param>
        /// <param name="username">Parsed user name.</param>
        /// <param name="password">Parsed password.</param>
        /// <returns><see langword="True"/> if the credentials were succesfully parsed from request information.</returns>
        public static bool GetAuthentication(Uri uri, DreamHeaders headers, out string username, out string password)
        {
            username = null;
            password = null;

            // Authorization = Basic 1YJ1TTpPcmx4bMQ=

            // check if a user/password pair was provided in the URI
            if (!string.IsNullOrEmpty(uri.UserInfo))
            {
                string[] userPwd = uri.UserInfo.Split(new char[] { ':' }, 2);
                username = XUri.Decode(userPwd[0]);
                password = XUri.Decode((userPwd.Length > 1) ? userPwd[1] : string.Empty);
                return(true);
            }
            else
            {
                // check if authorization is in the request header
                string header = headers[DreamHeaders.AUTHORIZATION];
                if (!string.IsNullOrEmpty(header))
                {
                    // extract authorization data
                    string[] value = header.Split(new char[] { ' ' }, 2);
                    if ((value.Length == 2) && StringUtil.EqualsInvariantIgnoreCase(value[0], "Basic"))
                    {
                        string[] userPwd = Encoding.UTF8.GetString(Convert.FromBase64String(value[1])).Split(new char[] { ':' }, 2);
                        username = userPwd[0];
                        password = (userPwd.Length > 1) ? userPwd[1] : string.Empty;
                        return(true);
                    }
                }
            }
            return(false);
        }
 //--- Constructors ---
 internal MockPlugInvocation(string verb, XUri uri, DreamMessage request, DreamHeaders responseHeaders)
 {
     Verb            = verb;
     Uri             = uri;
     Request         = request;
     ResponseHeaders = responseHeaders;
 }
Beispiel #3
0
        public void Parsing_unquoted_IfNoneMatch_does_not_alter_etag()
        {
            var ifNoneMatch = "dsfsdfsdfsdfsdf";
            var rawHeaders  = new NameValueCollection {
                { DreamHeaders.IF_NONE_MATCH, ifNoneMatch }
            };
            var headers = new DreamHeaders(rawHeaders);

            Assert.AreEqual(ifNoneMatch, headers.IfNoneMatch);
        }
Beispiel #4
0
        public void Parsing_single_quoted_IfNoneMatch_removes_quotes()
        {
            var ifNoneMatch = "dsfsdfsdfsdfsdf";
            var rawHeaders  = new NameValueCollection {
                { DreamHeaders.IF_NONE_MATCH, "'" + ifNoneMatch + "'" }
            };
            var headers = new DreamHeaders(rawHeaders);

            Assert.AreEqual(ifNoneMatch, headers.IfNoneMatch);
        }
Beispiel #5
0
        public void Parsing_unquoted_etag_does_not_alter_etag()
        {
            var etag       = "dsfsdfsdfsdfsdf";
            var rawHeaders = new NameValueCollection {
                { "etag", etag }
            };
            var headers = new DreamHeaders(rawHeaders);

            Assert.AreEqual(etag, headers.ETag);
        }
Beispiel #6
0
        public void Parsing_single_quoted_etag_removes_quotes()
        {
            var etag       = "dsfsdfsdfsdfsdf";
            var rawHeaders = new NameValueCollection {
                { "etag", "'" + etag + "'" }
            };
            var headers = new DreamHeaders(rawHeaders);

            Assert.AreEqual(etag, headers.ETag);
        }
Beispiel #7
0
 public void Get_via_internal_routing_follows_301_but_expects_query_to_be_in_location()
 {
     using (var hostInfo = DreamTestHelper.CreateRandomPortHost()) {
         var mock           = MockService.CreateMockService(hostInfo);
         var redirectCalled = 0;
         var targetCalled   = 0;
         mock.Service.CatchAllCallback = delegate(DreamContext context, DreamMessage request, Result <DreamMessage> response) {
             var msg     = "nothing here";
             var q       = context.Uri.GetParam("q");
             var forward = context.Uri.GetParam("forward");
             if (context.Uri.LastSegment == "redirect")
             {
                 _log.Debug("called redirect");
                 var redirect = context.Service.Self.Uri.At("target").AsPublicUri();
                 if (forward == "true")
                 {
                     redirect = redirect.With("q", q);
                 }
                 redirectCalled++;
                 var headers = new DreamHeaders();
                 headers.Add(DreamHeaders.LOCATION, redirect.ToString());
                 response.Return(new DreamMessage(DreamStatus.MovedPermanently, headers));
                 return;
             }
             if (context.Uri.LastSegment == "target")
             {
                 _log.Debug("called target");
                 if (q == "x")
                 {
                     _log.Debug("target request had query");
                     targetCalled++;
                     response.Return(DreamMessage.Ok());
                     return;
                 }
                 response.Return(DreamMessage.BadRequest("missing query param"));
                 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).With("q", "x").Get(new Result <DreamMessage>()).Wait();
         Assert.AreEqual(DreamStatus.BadRequest, r.Status);
         Assert.AreEqual(1, redirectCalled, "redirect without forward called incorrectly");
         Assert.AreEqual(0, targetCalled, "target without forward called incorrectly");
         redirectCalled = 0;
         targetCalled   = 0;
         r = Plug.New(uri).With("q", "x").With("forward", "true").Get(new Result <DreamMessage>()).Wait();
         Assert.IsTrue(r.IsSuccessful, r.HasDocument ? r.ToDocument()["message"].AsText : "request failed: " + r.Status);
         Assert.AreEqual(1, redirectCalled, "redirect with forward called incorrectly");
         Assert.AreEqual(1, targetCalled, "target with forward called incorrectly");
     }
 }
Beispiel #8
0
        public void Rendering_etag_leaves_single_quoted_value_alone()
        {
            var etag    = "dsfsdfsdfsdfsdf";
            var headers = new DreamHeaders {
                ETag = "'" + etag + "'"
            };
            var httpRequest = (HttpWebRequest)WebRequest.Create("http://localhost");

            HttpUtil.AddHeader(httpRequest, DreamHeaders.ETAG, headers.ETag);
            Assert.AreEqual("'" + etag + "'", httpRequest.Headers[DreamHeaders.ETAG]);
        }
Beispiel #9
0
 public void Preserve_order_of_hosts_in_forwarded_for_header()
 {
     // X-Forwarded-For
     var collections = new NameValueCollection();
     collections.Add("X-Forwarded-For", "a, b, c");
     collections.Add("X-Forwarded-For", "d, e");
     collections.Add("X-Forwarded-For", "f, g, h");
     var headers = new DreamHeaders(collections);
     var values = headers.ForwardedFor;
     Assert.AreEqual(new []{ "a", "b", "c", "d", "e", "f", "g", "h" }, values);
 }
Beispiel #10
0
        internal static XDoc ExecuteScript(Plug env, DreamHeaders headers, XDoc script) {

            // execute script commands
            XDoc reply = new XDoc("results");
            string ID = script["@ID"].Contents;
            if(!string.IsNullOrEmpty(ID)) {
                reply.Attr("ID", ID);
            }
            foreach(XDoc cmd in script.Elements) {
                reply.Add(ExecuteCommand(env, headers, cmd));
            }
            return reply;
        }
Beispiel #11
0
        public void Preserve_order_of_hosts_in_forwarded_for_header()
        {
            // X-Forwarded-For
            var collections = new NameValueCollection();

            collections.Add("X-Forwarded-For", "a, b, c");
            collections.Add("X-Forwarded-For", "d, e");
            collections.Add("X-Forwarded-For", "f, g, h");
            var headers = new DreamHeaders(collections);
            var values  = headers.ForwardedFor;

            Assert.AreEqual(new [] { "a", "b", "c", "d", "e", "f", "g", "h" }, values);
        }
Beispiel #12
0
 public void Get_via_internal_routing_follows_301_and_forwards_headers()
 {
     using (var hostInfo = DreamTestHelper.CreateRandomPortHost()) {
         var mock           = MockService.CreateMockService(hostInfo);
         var redirectCalled = 0;
         var targetCalled   = 0;
         mock.Service.CatchAllCallback = delegate(DreamContext context, DreamMessage request, Result <DreamMessage> response) {
             var msg = "nothing here";
             var h   = request.Headers["h"];
             if (context.Uri.LastSegment == "redirect")
             {
                 _log.Debug("called redirect");
                 if (h == "y")
                 {
                     redirectCalled++;
                     var headers = new DreamHeaders();
                     headers.Add(DreamHeaders.LOCATION, context.Service.Self.Uri.At("target").AsPublicUri().ToString());
                     response.Return(new DreamMessage(DreamStatus.MovedPermanently, headers));
                     return;
                 }
                 msg = "redirect request lacked header";
             }
             if (context.Uri.LastSegment == "target")
             {
                 _log.Debug("called target");
                 if (h == "y")
                 {
                     _log.Debug("target request had header");
                     targetCalled++;
                     response.Return(DreamMessage.Ok());
                     return;
                 }
                 msg = "target request lacked header ({1}";
             }
             _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").Get(new Result <DreamMessage>()).Wait();
         Assert.IsTrue(r.IsSuccessful, r.HasDocument ? r.ToDocument()["message"].AsText : "request failed: " + r.Status);
         Assert.AreEqual(1, redirectCalled, "redirect called incorrectly");
         Assert.AreEqual(1, targetCalled, "target called incorrectly");
     }
 }
Beispiel #13
0
 //--- Methods ---
 internal static XDoc ExecuteCommand(Plug env, DreamHeaders headers, XDoc cmd) {
     try {
         switch(cmd.Name.ToLowerInvariant()) {
         case "script":
             return ExecuteScript(env, headers, cmd);
         case "fork":
             return ExecuteFork(env, headers, cmd);
         case "action":
             return ExecuteAction(env, headers, cmd);
         case "pipe":
             return ExecutePipe(env, headers, cmd);
         default:
             throw new DreamException(string.Format("unregonized script command: " + cmd.Name.ToString()));
         }
     } catch(Exception e) {
         return new XException(e);
     }
 }
Beispiel #14
0
        public void Can_parse_bad_namevaluecollection_from_HttpContext()
        {
            var collections = new NameValueCollection {
                { "Cookie", "__utma=134392366.2030730348.1275932450.1276553042.1276556836.19; __utmz=134392366.1276207881.9.3.utmcsr=developer.mindtouch.com|utmccn=(referral)|utmcmd=referral|utmcct=/User:arnec/bugs; _mkto_trk=id:954-WGP-507&token:_mch-mindtouch.com-1270756717014-83706; WRUID=0; __kti=1274382964652" },
                { "Cookie", "http%3A%2F%2Fwww.mindtouch.com%2F" },
                { "Cookie", "; __ktv=2f4-f02d-634b-51e2128b724d7c2; __qca=P0-2102347259-1274460371553; PHPSESSID=307e779182909ab37932b4dffe77c40a; __utmc=134392366; __kts=1274382964673,http%3A%2F%2Fwww.mindtouch.com%2F,; __ktt=631f-d0a2-648e-e0b128b724d7c2; authtoken=\"1_634121336269193470_4254e33b49bc1ee0a72c5716200e296b\"; __utmb=134392366.6.10.1276556836" }
            };

            Assert.AreEqual(3, collections.GetValues("Cookie").Length);
            var headers = new DreamHeaders(collections);
            var cookies = headers.Cookies;

            Assert.AreEqual(13, cookies.Count);
            Assert.AreEqual("__utma", cookies[0].Name);
            Assert.AreEqual("134392366.2030730348.1275932450.1276553042.1276556836.19", cookies[0].Value);
            Assert.AreEqual("__utmz", cookies[1].Name);
            Assert.AreEqual("134392366.1276207881.9.3.utmcsr=developer.mindtouch.com|utmccn=(referral)|utmcmd=referral|utmcct=/User:arnec/bugs", cookies[1].Value);
            Assert.AreEqual("_mkto_trk", cookies[2].Name);
            Assert.AreEqual("id:954-WGP-507&token:_mch-mindtouch.com-1270756717014-83706", cookies[2].Value);
            Assert.AreEqual("WRUID", cookies[3].Name);
            Assert.AreEqual("0", cookies[3].Value);
            Assert.AreEqual("__kti", cookies[4].Name);
            Assert.AreEqual("1274382964652,http%3A%2F%2Fwww.mindtouch.com%2F,", cookies[4].Value);
            Assert.AreEqual("__ktv", cookies[5].Name);
            Assert.AreEqual("2f4-f02d-634b-51e2128b724d7c2", cookies[5].Value);
            Assert.AreEqual("__qca", cookies[6].Name);
            Assert.AreEqual("P0-2102347259-1274460371553", cookies[6].Value);
            Assert.AreEqual("PHPSESSID", cookies[7].Name);
            Assert.AreEqual("307e779182909ab37932b4dffe77c40a", cookies[7].Value);
            Assert.AreEqual("__utmc", cookies[8].Name);
            Assert.AreEqual("134392366", cookies[8].Value);
            Assert.AreEqual("__kts", cookies[9].Name);
            Assert.AreEqual("1274382964673,http%3A%2F%2Fwww.mindtouch.com%2F,", cookies[9].Value);
            Assert.AreEqual("__ktt", cookies[10].Name);
            Assert.AreEqual("631f-d0a2-648e-e0b128b724d7c2", cookies[10].Value);
            Assert.AreEqual("authtoken", cookies[11].Name);
            Assert.AreEqual("1_634121336269193470_4254e33b49bc1ee0a72c5716200e296b", cookies[11].Value);
            Assert.AreEqual("__utmb", cookies[12].Name);
            Assert.AreEqual("134392366.6.10.1276556836", cookies[12].Value);
        }
        /// <summary>
        /// Create a new <see cref="DreamMessage"/> instance containing payload and envelope.
        /// </summary>
        /// <returns></returns>
        public DreamMessage AsMessage()
        {
            DreamHeaders headers = new DreamHeaders();

            headers.DreamEventId = Id;
            if (Resource != null)
            {
                headers.DreamEventResource = Resource.ToString();
            }
            headers.DreamEventChannel = Channel.ToString();
            string[] origin = new string[Origins.Length];
            for (int i = 0; i < Origins.Length; i++)
            {
                origin[i] = Origins[i].ToString();
            }
            headers.DreamEventOrigin = origin;
            string[] recipients = new string[Recipients.Length];
            for (int i = 0; i < Recipients.Length; i++)
            {
                recipients[i] = Recipients[i].ToString();
            }
            headers.DreamEventRecipients = recipients;
            string[] via = new string[Via.Length];
            for (int i = 0; i < Via.Length; i++)
            {
                via[i] = Via[i].ToString();
            }
            headers.DreamEventVia = via;

            // if our message has a document as content, we can skip the whole stream business
            if (_message.HasDocument)
            {
                return(new DreamMessage(DreamStatus.Ok, headers, _message.ToDocument()));
            }

            // AsBytes will create the byte array only once, so we can call this multiple times without penalty
            byte[] bytes = _message.ToBytes();
            return(DreamMessage.Ok(_message.ContentType, bytes));
        }
Beispiel #16
0
 public void Can_parse_bad_namevaluecollection_from_HttpContext()
 {
     var collections = new NameValueCollection {
         { "Cookie", "__utma=134392366.2030730348.1275932450.1276553042.1276556836.19; __utmz=134392366.1276207881.9.3.utmcsr=developer.mindtouch.com|utmccn=(referral)|utmcmd=referral|utmcct=/User:arnec/bugs; _mkto_trk=id:954-WGP-507&token:_mch-mindtouch.com-1270756717014-83706; WRUID=0; __kti=1274382964652" },
         { "Cookie", "http%3A%2F%2Fwww.mindtouch.com%2F" },
         { "Cookie", "; __ktv=2f4-f02d-634b-51e2128b724d7c2; __qca=P0-2102347259-1274460371553; PHPSESSID=307e779182909ab37932b4dffe77c40a; __utmc=134392366; __kts=1274382964673,http%3A%2F%2Fwww.mindtouch.com%2F,; __ktt=631f-d0a2-648e-e0b128b724d7c2; authtoken=\"1_634121336269193470_4254e33b49bc1ee0a72c5716200e296b\"; __utmb=134392366.6.10.1276556836" }
     };
     Assert.AreEqual(3, collections.GetValues("Cookie").Length);
     var headers = new DreamHeaders(collections);
     var cookies = headers.Cookies;
     Assert.AreEqual(13, cookies.Count);
     Assert.AreEqual("__utma", cookies[0].Name);
     Assert.AreEqual("134392366.2030730348.1275932450.1276553042.1276556836.19", cookies[0].Value);
     Assert.AreEqual("__utmz", cookies[1].Name);
     Assert.AreEqual("134392366.1276207881.9.3.utmcsr=developer.mindtouch.com|utmccn=(referral)|utmcmd=referral|utmcct=/User:arnec/bugs", cookies[1].Value);
     Assert.AreEqual("_mkto_trk", cookies[2].Name);
     Assert.AreEqual("id:954-WGP-507&token:_mch-mindtouch.com-1270756717014-83706", cookies[2].Value);
     Assert.AreEqual("WRUID", cookies[3].Name);
     Assert.AreEqual("0", cookies[3].Value);
     Assert.AreEqual("__kti", cookies[4].Name);
     Assert.AreEqual("1274382964652,http%3A%2F%2Fwww.mindtouch.com%2F,", cookies[4].Value);
     Assert.AreEqual("__ktv", cookies[5].Name);
     Assert.AreEqual("2f4-f02d-634b-51e2128b724d7c2", cookies[5].Value);
     Assert.AreEqual("__qca", cookies[6].Name);
     Assert.AreEqual("P0-2102347259-1274460371553", cookies[6].Value);
     Assert.AreEqual("PHPSESSID", cookies[7].Name);
     Assert.AreEqual("307e779182909ab37932b4dffe77c40a", cookies[7].Value);
     Assert.AreEqual("__utmc", cookies[8].Name);
     Assert.AreEqual("134392366", cookies[8].Value);
     Assert.AreEqual("__kts", cookies[9].Name);
     Assert.AreEqual("1274382964673,http%3A%2F%2Fwww.mindtouch.com%2F,", cookies[9].Value);
     Assert.AreEqual("__ktt", cookies[10].Name);
     Assert.AreEqual("631f-d0a2-648e-e0b128b724d7c2", cookies[10].Value);
     Assert.AreEqual("authtoken", cookies[11].Name);
     Assert.AreEqual("1_634121336269193470_4254e33b49bc1ee0a72c5716200e296b", cookies[11].Value);
     Assert.AreEqual("__utmb", cookies[12].Name);
     Assert.AreEqual("134392366.6.10.1276556836", cookies[12].Value);
 }
Beispiel #17
0
        internal static XDoc ExecuteFork(Plug env, DreamHeaders headers, XDoc fork) {

            // execute script commands
            XDoc reply = new XDoc("results");
            string ID = fork["@ID"].Contents;
            if(!string.IsNullOrEmpty(ID)) {
                reply.Attr("ID", ID);
            }

            // TODO (steveb): we should use a 'fixed capacity' cue which marks itself as done when 'count' is reached

            XDoc forks = fork.Elements;
            foreach(XDoc cmd in forks) {

                // TODO (steveb): we should be doing this in parallel, not sequentially!

                try {
                    reply.Add(ExecuteCommand(env, headers, cmd));
                } catch(Exception e) {
                    reply.Add(new XException(e));
                }
            }
            return reply;
        }
Beispiel #18
0
 public void Get_via_internal_routing_follows_301_but_expects_query_to_be_in_location()
 {
     using(var hostInfo = DreamTestHelper.CreateRandomPortHost()) {
         var mock = MockService.CreateMockService(hostInfo);
         var redirectCalled = 0;
         var targetCalled = 0;
         mock.Service.CatchAllCallback = delegate(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
             var msg = "nothing here";
             var q = context.Uri.GetParam("q");
             var forward = context.Uri.GetParam("forward");
             if(context.Uri.LastSegment == "redirect") {
                 _log.Debug("called redirect");
                 var redirect = context.Service.Self.Uri.At("target").AsPublicUri();
                 if(forward == "true") {
                     redirect = redirect.With("q", q);
                 }
                 redirectCalled++;
                 var headers = new DreamHeaders();
                 headers.Add(DreamHeaders.LOCATION, redirect.ToString());
                 response.Return(new DreamMessage(DreamStatus.MovedPermanently, headers));
                 return;
             }
             if(context.Uri.LastSegment == "target") {
                 _log.Debug("called target");
                 if(q == "x") {
                     _log.Debug("target request had query");
                     targetCalled++;
                     response.Return(DreamMessage.Ok());
                     return;
                 }
                 response.Return(DreamMessage.BadRequest("missing query param"));
                 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).With("q", "x").GetAsync().Wait();
         Assert.AreEqual(DreamStatus.BadRequest, r.Status);
         Assert.AreEqual(1, redirectCalled, "redirect without forward called incorrectly");
         Assert.AreEqual(0, targetCalled, "target without forward called incorrectly");
         redirectCalled = 0;
         targetCalled = 0;
         r = Plug.New(uri).With("q", "x").With("forward", "true").GetAsync().Wait();
         Assert.IsTrue(r.IsSuccessful, r.HasDocument ? r.ToDocument()["message"].AsText : "request failed: " + r.Status);
         Assert.AreEqual(1, redirectCalled, "redirect with forward called incorrectly");
         Assert.AreEqual(1, targetCalled, "target with forward called incorrectly");
     }
 }
Beispiel #19
0
 public void Rendering_etag_quotes_unquoted_value()
 {
     var etag = "dsfsdfsdfsdfsdf";
     var headers = new DreamHeaders { ETag = etag };
     var httpRequest = (HttpWebRequest)WebRequest.Create("http://localhost");
     HttpUtil.AddHeader(httpRequest, DreamHeaders.ETAG, headers.ETag);
     Assert.AreEqual("\"" + etag + "\"", httpRequest.Headers[DreamHeaders.ETAG]);
 }
Beispiel #20
0
        /// <summary>
        /// Create a new message.
        /// </summary>
        /// <param name="status">Http status.</param>
        /// <param name="headers">Header collection.</param>
        /// <param name="contentType">Content Mime-Type</param>
        /// <param name="contentLength">Content byte langth</param>
        /// <param name="stream">Stream to uas as the source for the message's content.</param>
        public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, long contentLength, Stream stream) {
            this.Status = status;
            this.Headers = new DreamHeaders(headers);
            if(contentLength != -1) {
                this.Headers.ContentLength = contentLength;
            }
            this.Headers.ContentType = contentType ?? MimeType.DefaultMimeType;

            // set stream
            _stream = stream ?? Stream.Null;
            _streamOpen = !_stream.IsStreamMemorized();
        }
Beispiel #21
0
 public void Parsing_single_quoted_etag_removes_quotes()
 {
     var etag = "dsfsdfsdfsdfsdf";
     var rawHeaders = new NameValueCollection { { "etag", "'" + etag + "'" } };
     var headers = new DreamHeaders(rawHeaders);
     Assert.AreEqual(etag, headers.ETag);
 }
Beispiel #22
0
 public void Parsing_unquoted_etag_does_not_alter_etag()
 {
     var etag = "dsfsdfsdfsdfsdf";
     var rawHeaders = new NameValueCollection { { "etag", etag } };
     var headers = new DreamHeaders(rawHeaders);
     Assert.AreEqual(etag, headers.ETag);
 }
Beispiel #23
0
 /// <summary>
 /// Create a copy of the instance with a header added.
 /// </summary>
 /// <param name="name">Header name.</param>
 /// <param name="value">Header value.</param>
 /// <returns>New instance.</returns>
 public Plug WithHeader(string name, string value) {
     if(name == null) {
         throw new ArgumentNullException("name");
     }
     if(value == null) {
         throw new ArgumentNullException("value");
     }
     DreamHeaders newHeaders = new DreamHeaders(_headers);
     newHeaders.Add(name, value);
     return new Plug(Uri, Timeout, newHeaders, _preHandlers, _postHandlers, Credentials, _cookieJarOverride, MaxAutoRedirects);
 }
Beispiel #24
0
        /// <summary>
        /// Create a new <see cref="DreamMessage"/> instance containing payload and envelope.
        /// </summary>
        /// <returns></returns>
        public DreamMessage AsMessage()
        {
            DreamHeaders headers = new DreamHeaders();
            headers.DreamEventId = Id;
            if(Resource != null) {
                headers.DreamEventResource = Resource.ToString();
            }
            headers.DreamEventChannel = Channel.ToString();
            string[] origin = new string[Origins.Length];
            for(int i = 0; i < Origins.Length; i++) {
                origin[i] = Origins[i].ToString();
            }
            headers.DreamEventOrigin = origin;
            string[] recipients = new string[Recipients.Length];
            for(int i = 0; i < Recipients.Length; i++) {
                recipients[i] = Recipients[i].ToString();
            }
            headers.DreamEventRecipients = recipients;
            string[] via = new string[Via.Length];
            for(int i = 0; i < Via.Length; i++) {
                via[i] = Via[i].ToString();
            }
            headers.DreamEventVia = via;

            // if our message has a document as content, we can skip the whole stream business
            if(_message.HasDocument) {
                return new DreamMessage(DreamStatus.Ok, headers, _message.ToDocument());
            }

            // AsBytes will create the byte array only once, so we can call this multiple times without penalty
            byte[] bytes = _message.ToBytes();
            return DreamMessage.Ok(_message.ContentType, bytes);
        }
Beispiel #25
0
        private static DreamMessage PostProcess(string verb, XUri uri, XUri normalizedUri, DreamHeaders headers, DreamCookieJar cookies, DreamMessage message) {

            // check if we received cookies
            if(message.HasCookies) {

                // add matching cookies to service or to global cookie jar
                if(cookies != null) {
                    lock(cookies) {
                        if(!StringUtil.EqualsInvariant(uri.Scheme, "local") && StringUtil.EqualsInvariant(normalizedUri.Scheme, "local")) {

                            // need to translate cookies as they leave the dreamcontext
                            cookies.Update(DreamCookie.ConvertToPublic(message.Cookies), uri);
                        } else {
                            cookies.Update(message.Cookies, uri);
                        }
                    }
                }
            }
            return message;
        }
Beispiel #26
0
        //--- Constructors ---

        /// <summary>
        /// Create a new instance.
        /// </summary>
        /// <param name="uri">Uri to the resource to make the request against.</param>
        /// <param name="timeout">Invocation timeout.</param>
        /// <param name="headers">Header collection for request.</param>
        /// <param name="preHandlers">Optional pre-invocation handlers.</param>
        /// <param name="postHandlers">Optional post-invocation handlers.</param>
        /// <param name="credentials">Optional request credentials.</param>
        /// <param name="cookieJarOverride">Optional cookie jar to override global jar shared by <see cref="Plug"/> instances.</param>
        /// <param name="maxAutoRedirects">Maximum number of redirects to follow, 0 if non redirects should be followed.</param>
        public Plug(XUri uri, TimeSpan timeout, DreamHeaders headers, List<PlugHandler> preHandlers, List<PlugHandler> postHandlers, ICredentials credentials, DreamCookieJar cookieJarOverride, ushort maxAutoRedirects) {
            if(uri == null) {
                throw new ArgumentNullException("uri");
            }
            this.Uri = uri;
            this.Timeout = timeout;
            this.Credentials = credentials;
            _headers = headers;
            _preHandlers = preHandlers;
            _postHandlers = postHandlers;
            _cookieJarOverride = cookieJarOverride;
            _maxAutoRedirects = maxAutoRedirects;
        }
Beispiel #27
0
        /// <summary>
        /// Create a new message.
        /// </summary>
        /// <param name="status">Http status.</param>
        /// <param name="headers">Header collection.</param>
        /// <param name="contentType">Content Mime-Type.</param>
        /// <param name="doc">Message body.</param>
        public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, XDoc doc) {
            if(doc == null) {
                throw new ArgumentNullException("doc");
            }
            this.Status = status;
            this.Headers = new DreamHeaders(headers);

            // check if document is empty
            if(doc.IsEmpty) {

                // we store empty XML documents as text content; it causes less confusion for browsers
                this.Headers.ContentType = MimeType.TEXT;
                this.Headers.ContentLength = 0L;
                _doc = doc;
                _bytes = new byte[0];
            } else {
                this.Headers.ContentType = contentType ?? MimeType.XML;
                _doc = doc.Clone();
            }
        }
Beispiel #28
0
 /// <summary>
 /// Create a new message.
 /// </summary>
 /// <param name="status">Http status.</param>
 /// <param name="headers">Header collection.</param>
 /// <param name="contentType">Content Mime-Type.</param>
 /// <param name="text">Message body.</param>
 public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, string text)
     : this(status, headers, contentType, contentType.CharSet.GetBytes(text)) { }
Beispiel #29
0
        /// <summary>
        /// Create a new message.
        /// </summary>
        /// <param name="status">Http status.</param>
        /// <param name="headers">Header collection.</param>
        /// <param name="contentType">Content Mime-Type.</param>
        /// <param name="bytes">Message body.</param>
        public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, byte[] bytes) {
            if(bytes == null) {
                throw new ArgumentNullException("bytes");
            }
            this.Status = status;
            this.Headers = new DreamHeaders(headers);
            this.Headers.ContentLength = bytes.LongLength;
            this.Headers.ContentType = contentType ?? MimeType.DefaultMimeType;

            // set bytes
            _bytes = bytes;
        }
Beispiel #30
0
        /// <summary>
        /// WARNING: This method is thread-blocking.  Please avoid using it if possible.
        /// </summary>
        internal static XDoc ExecuteAction(Plug env, DreamHeaders headers, XDoc action) {
            string verb = action["@verb"].Contents;
            string path = action["@path"].Contents;
            if((path.Length > 0) && (path[0] == '/')) {
                path = path.Substring(1);
            }
            XUri uri;
            if(!XUri.TryParse(path, out uri)) {
                uri = env.Uri.AtAbsolutePath(path);
            }

            // create message
            DreamMessage message = DreamMessage.Ok(GetActionBody(action));
            message.Headers.AddRange(headers);

            // apply headers
            foreach(XDoc header in action["header"]) {
                message.Headers[header["@name"].Contents] = header.Contents;
            }

            // BUG #814: we need to support events

            // execute action
            DreamMessage reply = Plug.New(uri).Invoke(verb, message);

            // prepare response
            XDoc result = new XMessage(reply);
            string ID = action["@ID"].Contents;
            if(!string.IsNullOrEmpty(ID)) {
                result.Root.Attr("ID", ID);
            }
            return result;
        }
Beispiel #31
0
 /// <summary>
 /// Create a copy of the instance with a header collection added.
 /// </summary>
 /// <param name="headers">Header collection</param>
 /// <returns>New instance.</returns>
 public Plug WithHeaders(DreamHeaders headers) {
     if(headers != null) {
         DreamHeaders newHeaders = new DreamHeaders(_headers);
         newHeaders.AddRange(headers);
         return new Plug(Uri, Timeout, newHeaders, _preHandlers, _postHandlers, Credentials, _cookieJarOverride, MaxAutoRedirects);
     }
     return this;
 }
Beispiel #32
0
 public void Get_via_internal_routing_follows_301_and_forwards_headers()
 {
     using(var hostInfo = DreamTestHelper.CreateRandomPortHost()) {
         var mock = MockService.CreateMockService(hostInfo);
         var redirectCalled = 0;
         var targetCalled = 0;
         mock.Service.CatchAllCallback = delegate(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
             var msg = "nothing here";
             var h = request.Headers["h"];
             if(context.Uri.LastSegment == "redirect") {
                 _log.Debug("called redirect");
                 if(h == "y") {
                     redirectCalled++;
                     var headers = new DreamHeaders();
                     headers.Add(DreamHeaders.LOCATION, context.Service.Self.Uri.At("target").AsPublicUri().ToString());
                     response.Return(new DreamMessage(DreamStatus.MovedPermanently, headers));
                     return;
                 }
                 msg = "redirect request lacked header";
             }
             if(context.Uri.LastSegment == "target") {
                 _log.Debug("called target");
                 if(h == "y") {
                     _log.Debug("target request had header");
                     targetCalled++;
                     response.Return(DreamMessage.Ok());
                     return;
                 }
                 msg = "target request lacked header ({1}";
             }
             _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").GetAsync().Wait();
         Assert.IsTrue(r.IsSuccessful, r.HasDocument ? r.ToDocument()["message"].AsText : "request failed: " + r.Status);
         Assert.AreEqual(1, redirectCalled, "redirect called incorrectly");
         Assert.AreEqual(1, targetCalled, "target called incorrectly");
     }
 }
Beispiel #33
0
 /// <summary>
 /// Create a copy of the instance with a header removed.
 /// </summary>
 /// <param name="name">Name of the header to remove.</param>
 /// <returns>New instance.</returns>
 public Plug WithoutHeader(string name) {
     DreamHeaders newHeaders = null;
     if(_headers != null) {
         newHeaders = new DreamHeaders(_headers);
         newHeaders.Remove(name);
         if(newHeaders.Count == 0) {
             newHeaders = null;
         }
     }
     return new Plug(Uri, Timeout, newHeaders, _preHandlers, _postHandlers, Credentials, _cookieJarOverride, MaxAutoRedirects);
 }
Beispiel #34
0
        //--- Class Methods ---
        /// <summary>
        /// Retrieve user credentials from a request uri and/or headers.
        /// </summary>
        /// <param name="uri">Request uri.</param>
        /// <param name="headers">Request headers.</param>
        /// <param name="username">Parsed user name.</param>
        /// <param name="password">Parsed password.</param>
        /// <returns><see langword="True"/> if the credentials were succesfully parsed from request information.</returns>
        public static bool GetAuthentication(Uri uri, DreamHeaders headers, out string username, out string password)
        {
            username = null;
            password = null;

            // Authorization = Basic 1YJ1TTpPcmx4bMQ=

            // check if a user/password pair was provided in the URI
            if(!string.IsNullOrEmpty(uri.UserInfo)) {
                var userPwd = uri.UserInfo.Split(new[] { ':' }, 2);
                username = XUri.Decode(userPwd[0]);
                password = XUri.Decode((userPwd.Length > 1) ? userPwd[1] : string.Empty);
                return true;
            }

            // check if authorization is in the request header
            var header = headers[DreamHeaders.AUTHORIZATION];
            if(!string.IsNullOrEmpty(header)) {

                // extract authorization data
                var value = header.Split(new[] { ' ' }, 2);
                if((value.Length == 2) && value[0].EqualsInvariantIgnoreCase("Basic")) {
                    try {
                        var userPwd = Encoding.UTF8.GetString(Convert.FromBase64String(value[1])).Split(new[] { ':' }, 2);
                        username = userPwd[0];
                        password = (userPwd.Length > 1) ? userPwd[1] : string.Empty;
                        return true;
                    } catch {
                        throw new InvalidHttpAuthorizationHeader();
                    }
                }
            }
            return false;
        }
Beispiel #35
0
 //--- Constructors ---
 internal MockPlugInvocation(string verb, XUri uri, DreamMessage request, DreamHeaders responseHeaders) {
     Verb = verb;
     Uri = uri;
     Request = request;
     ResponseHeaders = responseHeaders;
 }
Beispiel #36
0
 public void Parsing_single_quoted_IfNoneMatch_removes_quotes()
 {
     var ifNoneMatch = "dsfsdfsdfsdfsdf";
     var rawHeaders = new NameValueCollection { { DreamHeaders.IF_NONE_MATCH, "'" + ifNoneMatch + "'" } };
     var headers = new DreamHeaders(rawHeaders);
     Assert.AreEqual(ifNoneMatch, headers.IfNoneMatch);
 }
Beispiel #37
0
        /// <summary>
        /// WARNING: This method is thread-blocking.  Please avoid using it if possible.
        /// </summary>
        internal static XDoc ExecutePipe(Plug env, DreamHeaders headers, XDoc pipe) {
            DreamMessage message = null;
            foreach(XDoc action in pipe["action"]) {
                string verb = action["@verb"].Contents;
                string path = action["@path"].Contents;
                XUri uri;
                if(!XUri.TryParse(path, out uri)) {
                    uri = env.Uri.AtPath(path);
                }

                // create first message
                if(message == null) {
                    message = DreamMessage.Ok(GetActionBody(action));
                }
                message.Headers.AddRange(headers);

                // apply headers
                foreach(XDoc header in action["header"]) {
                    message.Headers[header["@name"].Contents] = header.Contents;
                }

                // execute action
                message = Plug.New(uri).Invoke(verb, message);
                if(!message.IsSuccessful) {
                    break;
                }
            }

            // prepare response
            if(message == null) {
                return XDoc.Empty;
            }
            XDoc result = new XMessage(message);
            string ID = pipe["@ID"].Contents;
            if(!string.IsNullOrEmpty(ID)) {
                result.Root.Attr("ID", ID);
            }
            return result;
        }
Beispiel #38
0
 public void Parsing_unquoted_IfNoneMatch_does_not_alter_etag()
 {
     var ifNoneMatch = "dsfsdfsdfsdfsdf";
     var rawHeaders = new NameValueCollection { { DreamHeaders.IF_NONE_MATCH, ifNoneMatch } };
     var headers = new DreamHeaders(rawHeaders);
     Assert.AreEqual(ifNoneMatch, headers.IfNoneMatch);
 }
Beispiel #39
0
        //--- Constructors ---

        /// <summary>
        /// Create a new message.
        /// </summary>
        /// <param name="status">Http status.</param>
        /// <param name="headers">Header collection.</param>
        public DreamMessage(DreamStatus status, DreamHeaders headers) {
            this.Status = status;
            this.Headers = new DreamHeaders(headers);
            _bytes = new byte[0];
            _noContent = true;
        }
Beispiel #40
0
        private static DreamMessage PreProcess(string verb, XUri uri, XUri normalizedUri, DreamHeaders headers, DreamCookieJar cookies, DreamMessage message) {

            // check if plug is running in the context of a service
            DreamContext context = DreamContext.CurrentOrNull;
            if(context != null) {

                // set request id header
                message.Headers.DreamRequestId = context.GetState<string>(DreamHeaders.DREAM_REQUEST_ID);

                // set dream service header
                if(context.Service.Self != null) {
                    message.Headers.DreamService = context.AsPublicUri(context.Service.Self).ToString();
                }

                // check if uri is local://
                if(normalizedUri.Scheme.EqualsInvariant("local")) {
                    DreamUtil.AppendHeadersToInternallyForwardedMessage(context.Request, message);
                }
            }

            if(cookies != null) {
                lock(cookies) {
                    message.Cookies.AddRange(cookies.Fetch(uri));
                }
            }

            // transfer plug headers
            message.Headers.AddRange(headers);
            return message;
        }
Beispiel #41
0
 /// <summary>
 /// Create a new message.
 /// </summary>
 /// <param name="status">Http status.</param>
 /// <param name="headers">Header collection.</param>
 /// <param name="doc">Message body.</param>
 public DreamMessage(DreamStatus status, DreamHeaders headers, XDoc doc) : this(status, headers, MimeType.XML, doc) { }