HTTP handler for a POST to _bulk_get Request looks like POST /db/_bulk_get?revs=___&attachments=___ where the boolean ?revs parameter adds a revision history to each doc and the boolean ?attachments parameter includes attachment bodies. The body of the request is JSON and looks like: { "docs":
()
| 395 | // ] |
| 396 | // } |
| 397 | func (h *handler) handleBulkGet() error { |
| 398 | |
| 399 | includeAttachments := h.getBoolQuery("attachments") |
| 400 | showExp := h.getBoolQuery("show_exp") |
| 401 | |
| 402 | showRevs := h.getBoolQuery("revs") |
| 403 | globalRevsLimit := int(h.getIntQuery("revs_limit", math.MaxInt32)) |
| 404 | |
| 405 | // If a client passes the HTTP header "Accept-Encoding: gzip" then the header "X-Accept-Part-Encoding: gzip" will be |
| 406 | // ignored and the entire HTTP response will be gzip compressed. (aside from exception mentioned below for issue 1419) |
| 407 | acceptGzipPartEncoding := strings.Contains(h.rq.Header.Get("X-Accept-Part-Encoding"), "gzip") |
| 408 | acceptGzipEncoding := strings.Contains(h.rq.Header.Get("Accept-Encoding"), "gzip") |
| 409 | canCompressParts := acceptGzipPartEncoding && !acceptGzipEncoding |
| 410 | |
| 411 | // Exception: if the user agent is empty or earlier than 1.2, and X-Accept-Part-Encoding=gzip, then we actually |
| 412 | // DO want to compress the parts since the full response will not be gzipped, since those clients can't handle it. |
| 413 | // See https://github.com/couchbase/sync_gateway/issues/1419 and encoded_response_writer.go |
| 414 | userAgentVersion := NewUserAgentVersion(h.rq.Header.Get(base.HTTPHeaderUserAgent)) |
| 415 | if userAgentVersion.IsBefore(1, 2) && acceptGzipPartEncoding { |
| 416 | canCompressParts = true |
| 417 | } |
| 418 | |
| 419 | body, err := h.readJSON() |
| 420 | if err != nil { |
| 421 | return err |
| 422 | } |
| 423 | |
| 424 | docs, ok := body["docs"].([]interface{}) |
| 425 | if !ok { |
| 426 | return base.HTTPErrorf(http.StatusBadRequest, "missing 'docs' property") |
| 427 | } |
| 428 | |
| 429 | return h.writeMultipart("mixed", func(writer *multipart.Writer) error { |
| 430 | for _, item := range docs { |
| 431 | var body db.Body |
| 432 | var revsFrom, attsSince []string |
| 433 | var docRevsLimit int |
| 434 | var err error |
| 435 | |
| 436 | doc := item.(map[string]interface{}) |
| 437 | docid, _ := doc["id"].(string) |
| 438 | revOrCV := "" |
| 439 | revok := true |
| 440 | if doc["rev"] != nil { |
| 441 | revOrCV, revok = doc["rev"].(string) |
| 442 | } |
| 443 | if docid == "" || !revok { |
| 444 | err = base.HTTPErrorf(http.StatusBadRequest, "Invalid doc/rev ID in _bulk_get") |
| 445 | } else { |
| 446 | attsSince, err = db.GetStringArrayProperty(doc, "atts_since") |
| 447 | |
| 448 | if showRevs { |
| 449 | docRevsLimit = globalRevsLimit |
| 450 | |
| 451 | // Try to pull out a per-doc revs limit that can override the global one. |
| 452 | if raw, isSet := doc["revs_limit"]; isSet { |
| 453 | if val, ok := base.ToInt64(raw); ok && val >= 0 { |
| 454 | docRevsLimit = int(val) |
nothing calls this directly
no test coverage detected