// Update the given attachment using the provided info private static CouchbaseLiteResponse UpdateAttachment(ICouchbaseListenerContext context, Database db, string attachment, string docId, BlobStoreWriter body) { var castContext = context as ICouchbaseListenerContext2; var source = castContext != null && !castContext.IsLoopbackRequest ? castContext.Sender : null; RevisionInternal rev = db.UpdateAttachment(attachment, body, context.RequestHeaders["Content-Type"], AttachmentEncoding.None, docId, (context.GetQueryParam("rev") ?? context.IfMatch()).AsRevID(), source); var response = context.CreateResponse(); response.JsonBody = new Body(new Dictionary <string, object> { { "ok", true }, { "id", rev.DocID }, { "rev", rev.RevID } }); context.CacheWithEtag(rev.RevID.ToString()); if (body != null) { response["Location"] = context.RequestUrl.AbsoluteUri; } return(response); }
// Update the given attachment using the provided info private static CouchbaseLiteResponse UpdateAttachment(ICouchbaseListenerContext context, Database db, string attachment, string docId, BlobStoreWriter body) { RevisionInternal rev = db.UpdateAttachment(attachment, body, context.RequestHeaders["Content-Type"], AttachmentEncoding.None, docId, context.GetQueryParam("rev") ?? context.IfMatch()); var response = context.CreateResponse(); response.JsonBody = new Body(new Dictionary<string, object> { { "ok", true }, { "id", rev.GetDocId() }, { "rev", rev.GetRevId() } }); context.CacheWithEtag(rev.GetRevId()); if (body != null) { response["Location"] = context.RequestUrl.AbsoluteUri; } return response; }
/// <summary> /// Attempt to update a document based on the information in the HTTP request /// </summary> /// <returns>The resulting status of the operation</returns> /// <param name="context">The request context</param> /// <param name="db">The database in which the document exists</param> /// <param name="docId">The ID of the document being updated</param> /// <param name="body">The new document body</param> /// <param name="deleting">Whether or not the document is being deleted</param> /// <param name="allowConflict">Whether or not to allow a conflict to be inserted</param> /// <param name="outRev">The resulting revision of the document</param> public static StatusCode UpdateDocument(ICouchbaseListenerContext context, Database db, string docId, Body body, bool deleting, bool allowConflict, out RevisionInternal outRev) { outRev = null; if (body != null && !body.IsValidJSON()) { return(StatusCode.BadJson); } string prevRevId; if (!deleting) { var properties = body.GetProperties(); deleting = properties.GetCast <bool>("_deleted"); if (docId == null) { // POST's doc ID may come from the _id field of the JSON body. docId = properties.CblID(); if (docId == null && deleting) { return(StatusCode.BadId); } } // PUT's revision ID comes from the JSON body. prevRevId = properties.GetCast <string>("_rev"); } else { // DELETE's revision ID comes from the ?rev= query param prevRevId = context.GetQueryParam("rev"); } // A backup source of revision ID is an If-Match header: if (prevRevId == null) { prevRevId = context.IfMatch(); } if (docId == null && deleting) { return(StatusCode.BadId); } RevisionInternal rev = new RevisionInternal(docId, null, deleting); rev.SetBody(body); // Check for doc expiration var expirationTime = default(DateTime?); var tmp = default(object); var props = rev.GetProperties(); var hasValue = false; if (props != null && props.TryGetValue("_exp", out tmp)) { hasValue = true; if (tmp != null) { if (tmp is DateTime || tmp is DateTimeOffset) { expirationTime = (DateTime)tmp; } else { try { expirationTime = Convert.ToDateTime(tmp); } catch (Exception) { try { var num = Convert.ToInt64(tmp); expirationTime = Misc.OffsetFromEpoch(TimeSpan.FromSeconds(num)); } catch (Exception) { Log.To.Router.E(TAG, "Invalid value for _exp: {0}", tmp); return(StatusCode.BadRequest); } } } } props.Remove("_exp"); rev.SetProperties(props); } var castContext = context as ICouchbaseListenerContext2; var source = castContext != null && !castContext.IsLoopbackRequest ? castContext.Sender : null; StatusCode status = deleting ? StatusCode.Ok : StatusCode.Created; try { if (docId != null && docId.StartsWith("_local")) { if (expirationTime.HasValue) { return(StatusCode.BadRequest); } Log.To.Router.I(TAG, "Attempting to insert local {0} on top of {1} from PUT request", rev, prevRevId != null ? prevRevId.ToString() : "<root>"); outRev = db.Storage.PutLocalRevision(rev, prevRevId.AsRevID(), true); //TODO: Doesn't match iOS } else { Log.To.Router.I(TAG, "Attempting to insert {0} on top of {1} from PUT request", rev, prevRevId != null ? prevRevId.ToString() : "<root>"); outRev = db.PutRevision(rev, prevRevId.AsRevID(), allowConflict, source); if (hasValue) { db.Storage?.SetDocumentExpiration(rev.DocID, expirationTime); } } } catch (CouchbaseLiteException e) { status = e.Code; } return(status); }
/// <summary> /// Attempt to update a document based on the information in the HTTP request /// </summary> /// <returns>The resulting status of the operation</returns> /// <param name="context">The request context</param> /// <param name="db">The database in which the document exists</param> /// <param name="docId">The ID of the document being updated</param> /// <param name="body">The new document body</param> /// <param name="deleting">Whether or not the document is being deleted</param> /// <param name="allowConflict">Whether or not to allow a conflict to be inserted</param> /// <param name="outRev">The resulting revision of the document</param> public static StatusCode UpdateDocument(ICouchbaseListenerContext context, Database db, string docId, Body body, bool deleting, bool allowConflict, out RevisionInternal outRev) { outRev = null; if (body != null && !body.IsValidJSON()) { return StatusCode.BadJson; } string prevRevId; if (!deleting) { var properties = body.GetProperties(); deleting = properties.GetCast<bool>("_deleted"); if (docId == null) { // POST's doc ID may come from the _id field of the JSON body. docId = properties.GetCast<string>("_id"); if (docId == null && deleting) { return StatusCode.BadId; } } // PUT's revision ID comes from the JSON body. prevRevId = properties.GetCast<string>("_rev"); } else { // DELETE's revision ID comes from the ?rev= query param prevRevId = context.GetQueryParam("rev"); } // A backup source of revision ID is an If-Match header: if (prevRevId == null) { prevRevId = context.IfMatch(); } if (docId == null && deleting) { return StatusCode.BadId; } RevisionInternal rev = new RevisionInternal(docId, null, deleting); rev.SetBody(body); StatusCode status = StatusCode.Created; try { if (docId != null && docId.StartsWith("_local")) { outRev = db.Storage.PutLocalRevision(rev, prevRevId, true); //TODO: Doesn't match iOS } else { Status retStatus = new Status(); outRev = db.PutRevision(rev, prevRevId, allowConflict, retStatus); status = retStatus.Code; } } catch(CouchbaseLiteException e) { status = e.Code; } return status; }
// Update the given attachment using the provided info private static CouchbaseLiteResponse UpdateAttachment(ICouchbaseListenerContext context, Database db, string attachment, string docId, BlobStoreWriter body) { RevisionInternal rev = db.UpdateAttachment(attachment, body, context.RequestHeaders["Content-Type"], AttachmentEncoding.None, docId, context.GetQueryParam("rev") ?? context.IfMatch()); var response = context.CreateResponse(); response.JsonBody = new Body(new Dictionary <string, object> { { "ok", true }, { "id", rev.GetDocId() }, { "rev", rev.GetRevId() } }); context.CacheWithEtag(rev.GetRevId()); if (body != null) { response["Location"] = context.RequestUrl.AbsoluteUri; } return(response); }
/// <summary> /// Attempt to update a document based on the information in the HTTP request /// </summary> /// <returns>The resulting status of the operation</returns> /// <param name="context">The request context</param> /// <param name="db">The database in which the document exists</param> /// <param name="docId">The ID of the document being updated</param> /// <param name="body">The new document body</param> /// <param name="deleting">Whether or not the document is being deleted</param> /// <param name="allowConflict">Whether or not to allow a conflict to be inserted</param> /// <param name="outRev">The resulting revision of the document</param> public static StatusCode UpdateDocument(ICouchbaseListenerContext context, Database db, string docId, Body body, bool deleting, bool allowConflict, out RevisionInternal outRev) { outRev = null; if (body != null && !body.IsValidJSON()) { return(StatusCode.BadJson); } string prevRevId; if (!deleting) { var properties = body.GetProperties(); deleting = properties.GetCast <bool>("_deleted"); if (docId == null) { // POST's doc ID may come from the _id field of the JSON body. docId = properties.GetCast <string>("_id"); if (docId == null && deleting) { return(StatusCode.BadId); } } // PUT's revision ID comes from the JSON body. prevRevId = properties.GetCast <string>("_rev"); } else { // DELETE's revision ID comes from the ?rev= query param prevRevId = context.GetQueryParam("rev"); } // A backup source of revision ID is an If-Match header: if (prevRevId == null) { prevRevId = context.IfMatch(); } if (docId == null && deleting) { return(StatusCode.BadId); } RevisionInternal rev = new RevisionInternal(docId, null, deleting); rev.SetBody(body); StatusCode status = StatusCode.Created; try { if (docId.StartsWith("_local")) { outRev = db.PutLocalRevision(rev, prevRevId); //TODO: Doesn't match iOS } else { Status retStatus = new Status(); outRev = db.PutRevision(rev, prevRevId, allowConflict, retStatus); status = retStatus.GetCode(); } } catch (CouchbaseLiteException e) { status = e.Code; } return(status); }
// Update the given attachment using the provided info private static CouchbaseLiteResponse UpdateAttachment(ICouchbaseListenerContext context, Database db, string attachment, string docId, BlobStoreWriter body) { var castContext = context as ICouchbaseListenerContext2; var source = castContext != null && !castContext.IsLoopbackRequest ? castContext.Sender : null; RevisionInternal rev = db.UpdateAttachment(attachment, body, context.RequestHeaders["Content-Type"], AttachmentEncoding.None, docId, (context.GetQueryParam("rev") ?? context.IfMatch()).AsRevID(), source); var response = context.CreateResponse(); response.JsonBody = new Body(new Dictionary<string, object> { { "ok", true }, { "id", rev.DocID }, { "rev", rev.RevID } }); context.CacheWithEtag(rev.RevID.ToString()); if (body != null) { response["Location"] = context.RequestUrl.AbsoluteUri; } return response; }
/// <summary> /// Attempt to update a document based on the information in the HTTP request /// </summary> /// <returns>The resulting status of the operation</returns> /// <param name="context">The request context</param> /// <param name="db">The database in which the document exists</param> /// <param name="docId">The ID of the document being updated</param> /// <param name="body">The new document body</param> /// <param name="deleting">Whether or not the document is being deleted</param> /// <param name="allowConflict">Whether or not to allow a conflict to be inserted</param> /// <param name="outRev">The resulting revision of the document</param> public static StatusCode UpdateDocument(ICouchbaseListenerContext context, Database db, string docId, Body body, bool deleting, bool allowConflict, out RevisionInternal outRev) { outRev = null; if (body != null && !body.IsValidJSON()) { return StatusCode.BadJson; } string prevRevId; if (!deleting) { var properties = body.GetProperties(); deleting = properties.GetCast<bool>("_deleted"); if (docId == null) { // POST's doc ID may come from the _id field of the JSON body. docId = properties.CblID(); if (docId == null && deleting) { return StatusCode.BadId; } } // PUT's revision ID comes from the JSON body. prevRevId = properties.GetCast<string>("_rev"); } else { // DELETE's revision ID comes from the ?rev= query param prevRevId = context.GetQueryParam("rev"); } // A backup source of revision ID is an If-Match header: if (prevRevId == null) { prevRevId = context.IfMatch(); } if (docId == null && deleting) { return StatusCode.BadId; } RevisionInternal rev = new RevisionInternal(docId, null, deleting); rev.SetBody(body); // Check for doc expiration var expirationTime = default(DateTime?); var tmp = default(object); var props = rev.GetProperties(); var hasValue = false; if(props != null && props.TryGetValue("_exp", out tmp)) { hasValue = true; if(tmp != null) { try { expirationTime = Convert.ToDateTime(tmp); } catch(Exception) { try { var num = Convert.ToInt64(tmp); expirationTime = Misc.OffsetFromEpoch(TimeSpan.FromSeconds(num)); } catch(Exception) { Log.To.Router.E(TAG, "Invalid value for _exp: {0}", tmp); return StatusCode.BadRequest; } } } props.Remove("_exp"); rev.SetProperties(props); } var castContext = context as ICouchbaseListenerContext2; var source = castContext != null && !castContext.IsLoopbackRequest ? castContext.Sender : null; StatusCode status = deleting ? StatusCode.Ok : StatusCode.Created; try { if(docId != null && docId.StartsWith("_local")) { if(expirationTime.HasValue) { return StatusCode.BadRequest; } outRev = db.Storage.PutLocalRevision(rev, prevRevId.AsRevID(), true); //TODO: Doesn't match iOS } else { outRev = db.PutRevision(rev, prevRevId.AsRevID(), allowConflict, source); if(hasValue) { db.Storage?.SetDocumentExpiration(rev.DocID, expirationTime); } } } catch(CouchbaseLiteException e) { status = e.Code; } return status; }