HTTP handler for a PUT of a document
()
| 566 | |
| 567 | // HTTP handler for a PUT of a document |
| 568 | func (h *handler) handlePutDoc() error { |
| 569 | |
| 570 | if h.isReadOnlyGuest() { |
| 571 | return base.HTTPErrorf(http.StatusForbidden, auth.GuestUserReadOnly) |
| 572 | } |
| 573 | |
| 574 | if h.db.DatabaseContext.Options.UnsupportedOptions != nil && h.db.DatabaseContext.Options.UnsupportedOptions.RejectWritesWithSkippedSequences { |
| 575 | // if we are in slow broadcast mode reject write with 503 and increment rejected writes stat |
| 576 | if h.db.BroadcastSlowMode.Load() { |
| 577 | h.db.DbStats.DatabaseStats.NumDocWritesRejected.Add(1) |
| 578 | return base.HTTPErrorf(http.StatusServiceUnavailable, "Database cache is behind and cannot accept writes at this time. Please try again later.") |
| 579 | } |
| 580 | } |
| 581 | |
| 582 | startTime := time.Now() |
| 583 | defer func() { |
| 584 | h.db.DbStats.CBLReplicationPush().WriteProcessingTime.Add(time.Since(startTime).Nanoseconds()) |
| 585 | }() |
| 586 | |
| 587 | docid := h.PathVar("docid") |
| 588 | |
| 589 | roundTrip := h.getBoolQuery("roundtrip") |
| 590 | |
| 591 | if replicator2, _ := h.getOptBoolQuery("replicator2", false); replicator2 { |
| 592 | return h.handlePutDocReplicator2(docid, roundTrip) |
| 593 | } |
| 594 | |
| 595 | body, err := h.readDocument() |
| 596 | if err != nil { |
| 597 | return err |
| 598 | } |
| 599 | |
| 600 | if body == nil { |
| 601 | return base.ErrEmptyDocument |
| 602 | } |
| 603 | |
| 604 | if bodyDocID, ok := body[db.BodyId].(string); ok && bodyDocID != docid { |
| 605 | return base.HTTPErrorf(http.StatusBadRequest, "The document ID provided in the body does not match the document ID in the path") |
| 606 | } |
| 607 | |
| 608 | var newRev string |
| 609 | var doc *db.Document |
| 610 | |
| 611 | if h.getQuery("new_edits") != "false" { |
| 612 | // Regular PUT: |
| 613 | |
| 614 | // occValue is the optimistic concurrency control value, which can be either the current rev ID or CV - used to prevent lost updates. |
| 615 | // we grab occValue from either query param, Etag header, or request body (in that order) |
| 616 | occValue, occValueType, err := h.getOCCValue(body) |
| 617 | if err != nil { |
| 618 | return err |
| 619 | } |
| 620 | |
| 621 | // set OCC version body value for Put |
| 622 | bodyKey, err := bodyKeyForOCCVersionType(occValueType) |
| 623 | if err != nil { |
| 624 | return base.HTTPErrorf(http.StatusBadRequest, "Invalid OCC version type: %v", err) |
| 625 | } |
nothing calls this directly
no test coverage detected