Beispiel #1
0
 /// <summary>This method is called when a part's headers have been parsed, before its data is parsed.
 ///     </summary>
 /// <remarks>This method is called when a part's headers have been parsed, before its data is parsed.
 ///     </remarks>
 public void StartedPart(IDictionary <string, string> headers)
 {
     if (_docReader != null)
     {
         throw new InvalidOperationException("_docReader is already defined");
     }
     Log.V(Tag, "{0}: Starting new document; headers ={1}", this, headers);
     Log.V(Tag, "{0}: Starting new document; ID={1}".Fmt(this, headers.Get("X-Doc-Id")));
     _docReader = new MultipartDocumentReader(db);
     _docReader.SetContentType(headers.Get("Content-Type"));
     _docReader.StartedPart(headers);
 }
Beispiel #2
0
 /// <summary>This method is called when a part is complete.</summary>
 /// <remarks>This method is called when a part is complete.</remarks>
 public virtual void FinishedPart()
 {
     Log.V(Tag, "{0}: Finished document".Fmt(this));
     if (_docReader == null)
     {
         throw new InvalidOperationException("_docReader is not defined");
     }
     _docReader.Finish();
     ++_docCount;
     OnDocumentDownloaded(_docReader.GetDocumentProperties());
     _docReader = null;
 }
Beispiel #3
0
 /// <summary>This method is called when a part is complete.</summary>
 /// <remarks>This method is called when a part is complete.</remarks>
 public virtual void FinishedPart()
 {
     Log.V(Log.TagSync, "%s: Finished document", this);
     if (_docReader == null)
     {
         throw new InvalidOperationException("_docReader is not defined");
     }
     _docReader.Finish();
     ++_docCount;
     _onDocument.OnDocument(_docReader.GetDocumentProperties());
     _docReader = null;
 }
Beispiel #4
0
        /// <summary>This method is called when a part's headers have been parsed, before its data is parsed.
        ///     </summary>
        /// <remarks>This method is called when a part's headers have been parsed, before its data is parsed.
        ///     </remarks>
        public void StartedPart(IDictionary <string, string> headers)
        {
            if (_docReader != null)
            {
                Log.To.Sync.E(Tag, "StartedPart called on an already started object");
                throw new InvalidOperationException("StartedPart called on an already started object");
            }

            Log.To.Sync.V(Tag, "{0}: Starting new document; ID={1}", this, headers.Get("X-Doc-ID"));
            _docReader = new MultipartDocumentReader(_db);
            _docReader.SetContentType(headers.Get("Content-Type"));
            _docReader.StartedPart(headers);
        }
Beispiel #5
0
 /// <summary>This method is called when a part's headers have been parsed, before its data is parsed.
 ///     </summary>
 /// <remarks>This method is called when a part's headers have been parsed, before its data is parsed.
 ///     </remarks>
 public virtual void StartedPart(IDictionary headers)
 {
     if (_docReader != null)
     {
         throw new InvalidOperationException("_docReader is already defined");
     }
     Log.V(Log.TagSync, "%s: Starting new document; headers =%s", this, headers);
     Log.V(Log.TagSync, "%s: Starting new document; ID=%s", this, headers.Get("X-Doc-Id"
                                                                              ));
     _docReader = new MultipartDocumentReader(null, _db);
     _docReader.SetContentType((string)headers.Get("Content-Type"));
     _docReader.StartedPart(headers);
 }
Beispiel #6
0
        /// <summary>This method is called when a part is complete.</summary>
        /// <remarks>This method is called when a part is complete.</remarks>
        public virtual void FinishedPart()
        {
            if (_docReader == null)
            {
                Log.To.Sync.E(Tag, "FinishedPart called on a non-started object");
                throw new InvalidOperationException("FinishedPart called on a non-started object");
            }

            Log.To.Sync.V(Tag, "{0} Finished document", this);
            _docReader.Finish();
            ++_docCount;
            OnDocumentDownloaded(_docReader.GetDocumentProperties());
            _docReader = null;
        }
Beispiel #7
0
        // Factors out the logic of opening the database and reading the document body from the HTTP request
        // and performs the specified logic on the body received in the request, barring any problems
        private static CouchbaseLiteResponse PerformLogicWithDocumentBody(ICouchbaseListenerContext context,
                                                                          Func <Database, Body, CouchbaseLiteResponse> callback)
        {
            return(DatabaseMethods.PerformLogicWithDatabase(context, true, db =>
            {
                MultipartDocumentReader reader = new MultipartDocumentReader(db);
                reader.SetContentType(context.RequestHeaders["Content-Type"]);
                reader.AppendData(context.BodyStream.ReadAllBytes());
                try {
                    reader.Finish();
                } catch (InvalidOperationException) {
                    return context.CreateResponse(StatusCode.BadRequest);
                }

                return callback(db, new Body(reader.GetDocumentProperties()));
            }));
        }
        // Factors out the logic of opening the database and reading the document body from the HTTP request
        // and performs the specified logic on the body received in the request, barring any problems
        private static CouchbaseLiteResponse PerformLogicWithDocumentBody(ICouchbaseListenerContext context,
                                                                          Func <Database, Body, CouchbaseLiteResponse> callback)
        {
            return(DatabaseMethods.PerformLogicWithDatabase(context, true, db =>
            {
                MultipartDocumentReader reader = new MultipartDocumentReader(db);
                reader.SetContentType(context.RequestHeaders["Content-Type"]);

                try {
                    reader.AppendData(context.BodyStream.ReadAllBytes());
                    reader.Finish();
                } catch (InvalidOperationException e) {
                    Log.To.Router.E(TAG, "Exception trying to read data from multipart upload", e);
                    return context.CreateResponse(StatusCode.BadRequest);
                } catch (IOException e) {
                    Log.To.Router.E(TAG, "IOException while reading context body", e);
                    return context.CreateResponse(StatusCode.RequestTimeout);
                }

                return callback(db, new Body(reader.GetDocumentProperties()));
            }));
        }
Beispiel #9
0
        internal void SendAsyncMultipartDownloaderRequest(HttpMethod method, string relativePath, object body, Database db, RemoteRequestCompletionBlock onCompletion)
        {
            try {
                var url = _baseUrl.Append(relativePath);

                var message = new HttpRequestMessage(method, url);
                message.Headers.Add("Accept", "*/*");
                AddRequestHeaders(message);

                var client = default(CouchbaseLiteHttpClient);
                if (!_client.AcquireFor(TimeSpan.FromSeconds(1), out client))
                {
                    Log.To.Sync.I(Tag, "Client is disposed, aborting request to {0}", new SecureLogString(relativePath, LogMessageSensitivity.PotentiallyInsecure));
                    return;
                }

                client.Authenticator = Authenticator;
                var request = client.SendAsync(message, _cancellationTokenSource.Token).ContinueWith(new Action <Task <HttpResponseMessage> >(responseMessage =>
                {
                    object fullBody = null;
                    Exception error = null;
                    try {
                        if (responseMessage.IsFaulted)
                        {
                            error = responseMessage.Exception.InnerException;
                            if (onCompletion != null)
                            {
                                onCompletion(null, error);
                            }

                            return;
                        }

                        var response = responseMessage.Result;
                        // add in cookies to global store
                        //CouchbaseLiteHttpClientFactory.Instance.AddCoIokies(clientFactory.HttpHandler.CookieContainer.GetCookies(url));

                        var status = response.StatusCode;
                        if ((Int32)status.GetStatusCode() >= 300)
                        {
                            Log.To.Sync.W(Tag, "Got error {0}", status.GetStatusCode());
                            Log.To.Sync.W(Tag, "Request was for: " + message);
                            Log.To.Sync.W(Tag, "Status reason: " + response.ReasonPhrase);
                            Log.To.Sync.W(Tag, "Passing error onto callback...");
                            error = new HttpResponseException(status);
                            if (onCompletion != null)
                            {
                                onCompletion(null, error);
                            }
                        }
                        else
                        {
                            var entity            = response.Content;
                            var contentTypeHeader = response.Content.Headers.ContentType;
                            Stream inputStream    = null;
                            if (contentTypeHeader != null && contentTypeHeader.ToString().Contains("multipart/related"))
                            {
                                try {
                                    var reader      = new MultipartDocumentReader(db);
                                    var contentType = contentTypeHeader.ToString();
                                    reader.SetContentType(contentType);

                                    var inputStreamTask = entity.ReadAsStreamAsync();
                                    //inputStreamTask.Wait(90000, CancellationTokenSource.Token);
                                    inputStream = inputStreamTask.Result;

                                    const int bufLen = 1024;
                                    var buffer       = new byte[bufLen];

                                    int numBytesRead = 0;
                                    while ((numBytesRead = inputStream.Read(buffer, 0, buffer.Length)) > 0)
                                    {
                                        if (numBytesRead != bufLen)
                                        {
                                            var bufferToAppend = new Couchbase.Lite.Util.ArraySegment <Byte>(buffer, 0, numBytesRead);
                                            reader.AppendData(bufferToAppend);
                                        }
                                        else
                                        {
                                            reader.AppendData(buffer);
                                        }
                                    }

                                    reader.Finish();
                                    fullBody = reader.GetDocumentProperties();

                                    if (onCompletion != null)
                                    {
                                        onCompletion(fullBody, error);
                                    }
                                } catch (Exception ex) {
                                    Log.To.Sync.W(Tag, "SendAsyncMultipartDownloaderRequest got an exception, aborting...", ex);
                                } finally {
                                    try {
                                        inputStream.Close();
                                    } catch (Exception) { }
                                }
                            }
                            else
                            {
                                if (entity != null)
                                {
                                    try {
                                        var readTask = entity.ReadAsStreamAsync();
                                        //readTask.Wait(); // TODO: This should be scaled based on content length.
                                        inputStream = readTask.Result;
                                        fullBody    = Manager.GetObjectMapper().ReadValue <Object>(inputStream);
                                        if (onCompletion != null)
                                        {
                                            onCompletion(fullBody, error);
                                        }
                                    } catch (Exception ex) {
                                        Log.To.Sync.W(Tag, "SendAsyncMultipartDownloaderRequest got an exception, aborting...", ex);
                                    } finally {
                                        try {
                                            inputStream.Close();
                                        } catch (Exception) { }
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        Log.To.Sync.W(Tag, "Got exception during SendAsyncMultipartDownload, aborting...");
                        error = e;
                    } finally {
                        Task dummy;
                        _requests.TryRemove(message, out dummy);
                        responseMessage.Result.Dispose();
                    }
                }), _workExecutor.Scheduler);
                _requests.TryAdd(message, request);
            } catch (UriFormatException e) {
                Log.To.Sync.W(Tag, "Malformed URL for async request, aborting...", e);
            }
        }
Beispiel #10
0
        public void TestMultipartDocumentReader()
        {
            var mime    = GetType().GetResourceAsStream("Multipart1.mime").ReadAllBytes();
            var headers = new Dictionary <string, string> {
                { "Content-Type", "multipart/mixed; boundary=\"BOUNDARY\"" }
            };

            var dict = default(IDictionary <string, object>);

            Assert.DoesNotThrow(() => dict = MultipartDocumentReader.ReadToDatabase(mime, headers, database));

            AssertDictionariesAreEqual(new Dictionary <string, object> {
                { "_id", "THX-1138" },
                { "_rev", "1-foobar" },
                { "_attachments", new Dictionary <string, object> {
                      { "mary.txt", new Dictionary <string, object> {
                            { "type", "text/doggerel" },
                            { "length", 52 },
                            { "follows", true },
                            { "digest", "sha1-Jcy8i3K9HZ8UGLO9j+KNbLLjm7M=" }
                        } }
                  } }
            }, dict);

            var attachment = dict.Get("_attachments").AsDictionary <string, object>().Get("mary.txt").AsDictionary <string, object>();
            var writer     = database.AttachmentWriterForAttachment(attachment);

            Assert.IsNotNull(writer);
            Assert.AreEqual(52, writer.GetLength());

            mime = GetType().GetResourceAsStream("MultipartBinary.mime").ReadAllBytes();
            headers["Content-Type"]        = "multipart/mixed; boundary=\"dc0bf3cdc9a6c6e4c46fe2a361c8c5d7\"";
            Assert.DoesNotThrow(() => dict = MultipartDocumentReader.ReadToDatabase(mime, headers, database));
            AssertDictionariesAreEqual(new Dictionary <string, object> {
                { "_id", "038c536dc29ff0f4127705879700062c" },
                { "_rev", "3-e715bcf1865f8283ab1f0ba76e7a92ba" },
                { "_attachments", new Dictionary <string, object> {
                      { "want3.jpg", new Dictionary <string, object> {
                            { "content_type", "image/jpeg" },
                            { "revpos", 3 },
                            { "length", 24758 },
                            { "follows", true },
                            { "digest", "sha1-mmlbbSUTrKoaD67j7Hyjgq2y1aI=" }
                        } },
                      { "Toad.gif", new Dictionary <string, object> {
                            { "content_type", "image/gif" },
                            { "revpos", 2 },
                            { "length", 6566 },
                            { "follows", true },
                            { "digest", "sha1-Y8ppBwk8w1j6nP5rwmeB8FwPtgg=" }
                        } }
                  } }
            }, dict);

            attachment = dict.Get("_attachments").AsDictionary <string, object>().Get("Toad.gif").AsDictionary <string, object>();
            writer     = database.AttachmentWriterForAttachment(attachment);
            Assert.IsNotNull(writer);
            Assert.AreEqual(6566, writer.GetLength());
            attachment = dict.Get("_attachments").AsDictionary <string, object>().Get("want3.jpg").AsDictionary <string, object>();
            writer     = database.AttachmentWriterForAttachment(attachment);
            Assert.IsNotNull(writer);
            Assert.AreEqual(24758, writer.GetLength());

            // Read data that's equivalent to the last one except the JSON is gzipped:
            mime = GetType().GetResourceAsStream("MultipartGZipped.mime").ReadAllBytes();
            headers["Content-Type"] = "multipart/mixed; boundary=\"d7a34c160fd136b5baf17055012e611abcb45dd3fe39fb81831ffd5dc920\"";
            var unzippedDict = default(IDictionary <string, object>);

            Assert.DoesNotThrow(() => unzippedDict = MultipartDocumentReader.ReadToDatabase(mime, headers, database));
            AssertDictionariesAreEqual(dict, unzippedDict);
        }
Beispiel #11
0
        internal void SendAsyncMultipartDownloaderRequest(HttpMethod method, string relativePath, object body, Database db, RemoteRequestCompletionBlock onCompletion)
        {
            try
            {
                var urlStr = BuildRelativeURLString(relativePath);
                var url    = new Uri(urlStr);

                var message = new HttpRequestMessage(method, url);
                message.Headers.Add("Accept", "*/*");
                AddRequestHeaders(message);

                var httpClient = clientFactory.GetHttpClient();
                httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead, CancellationTokenSource.Token)
                .ContinueWith(new Action <Task <HttpResponseMessage> >(responseMessage => {
                    object fullBody = null;
                    Exception error = null;
                    try
                    {
                        var response = responseMessage.Result;
                        // add in cookies to global store
                        CouchbaseLiteHttpClientFactory.Instance.AddCookies(clientFactory.HttpHandler.CookieContainer.GetCookies(url));

                        var status = response.StatusCode;
                        if ((Int32)status.GetStatusCode() >= 300)
                        {
                            Log.E(Database.Tag, "Got error " + Sharpen.Extensions.ToString(status.GetStatusCode
                                                                                               ()));
                            Log.E(Database.Tag, "Request was for: " + message);
                            Log.E(Database.Tag, "Status reason: " + response.ReasonPhrase);
                            error = new HttpException((Int32)status.GetStatusCode(), response.ReasonPhrase);
                        }
                        else
                        {
                            var entity              = response.Content;
                            var contentTypeHeader   = response.Content.Headers.ContentType;
                            InputStream inputStream = null;
                            if (contentTypeHeader != null && contentTypeHeader.ToString().Contains("multipart/related"))
                            {
                                try
                                {
                                    var reader = new MultipartDocumentReader(responseMessage.Result, LocalDatabase);
                                    reader.SetContentType(contentTypeHeader.MediaType);

                                    var inputStreamTask = entity.ReadAsStreamAsync();
                                    inputStreamTask.Wait(90000, CancellationTokenSource.Token);

                                    const int bufLen = 1024;
                                    var buffer       = new byte[bufLen];

                                    int numBytesRead = 0;
                                    while ((numBytesRead = inputStream.Read(buffer)) != -1)
                                    {
                                        if (numBytesRead != bufLen)
                                        {
                                            var bufferToAppend = new ArraySegment <Byte>(buffer, 0, numBytesRead).Array;
                                            reader.AppendData(bufferToAppend);
                                        }
                                        else
                                        {
                                            reader.AppendData(buffer);
                                        }
                                    }

                                    reader.Finish();
                                    fullBody = reader.GetDocumentProperties();

                                    if (onCompletion != null)
                                    {
                                        onCompletion(fullBody, error);
                                    }
                                }
                                finally
                                {
                                    try
                                    {
                                        inputStream.Close();
                                    }
                                    catch (IOException)
                                    {
                                        // NOTE: swallow?
                                    }
                                }
                            }
                            else
                            {
                                if (entity != null)
                                {
                                    try
                                    {
                                        var readTask = entity.ReadAsStreamAsync();
                                        readTask.Wait(); // TODO: This should be scaled based on content length.
                                        inputStream = readTask.Result;
                                        fullBody    = Manager.GetObjectMapper().ReadValue <Object>(inputStream);
                                        if (onCompletion != null)
                                        {
                                            onCompletion(fullBody, error);
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Log.E(Tag, ex.Message);
                                    }
                                    finally
                                    {
                                        try
                                        {
                                            inputStream.Close();
                                        }
                                        catch (IOException)
                                        {
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch (ProtocolViolationException e)
                    {
                        Log.E(Database.Tag, "client protocol exception", e);
                        error = e;
                    }
                    catch (IOException e)
                    {
                        Log.E(Database.Tag, "io exception", e);
                        error = e;
                    }
                }));
            }
            catch (UriFormatException e)
            {
                Log.E(Database.Tag, "Malformed URL for async request", e);
            }
        }