HTTP handler for a GET of a specific doc attachment
()
| 241 | |
| 242 | // HTTP handler for a GET of a specific doc attachment |
| 243 | func (h *handler) handleGetAttachment() error { |
| 244 | docid := h.PathVar("docid") |
| 245 | attachmentName := h.PathVar("attach") |
| 246 | revid := h.getQuery("rev") |
| 247 | rev, err := h.collection.GetRev(h.ctx(), docid, revid, false, nil) |
| 248 | if err != nil { |
| 249 | return err |
| 250 | } |
| 251 | if rev.BodyBytes == nil { |
| 252 | return kNotFoundError |
| 253 | } |
| 254 | |
| 255 | meta, ok := rev.Attachments[attachmentName].(map[string]interface{}) |
| 256 | if !ok { |
| 257 | return base.HTTPErrorf(http.StatusNotFound, "missing attachment %s", attachmentName) |
| 258 | } |
| 259 | digest := meta["digest"].(string) |
| 260 | version, ok := db.GetAttachmentVersion(meta) |
| 261 | if !ok { |
| 262 | return db.ErrAttachmentVersion |
| 263 | } |
| 264 | attachmentKey := db.MakeAttachmentKey(version, docid, digest) |
| 265 | data, err := h.collection.GetAttachment(attachmentKey) |
| 266 | if err != nil { |
| 267 | return err |
| 268 | } |
| 269 | |
| 270 | metaOption := h.getBoolQuery("meta") |
| 271 | if metaOption { |
| 272 | meta["key"] = attachmentKey |
| 273 | h.writeJSONStatus(http.StatusOK, meta) |
| 274 | return nil |
| 275 | } |
| 276 | |
| 277 | status, start, end := h.handleRange(uint64(len(data))) |
| 278 | if status > 299 { |
| 279 | return base.HTTPErrorf(status, "") |
| 280 | } else if status == http.StatusPartialContent { |
| 281 | data = data[start:end] |
| 282 | } |
| 283 | h.setHeader("Content-Length", strconv.FormatUint(uint64(len(data)), 10)) |
| 284 | |
| 285 | // #720 |
| 286 | setContentDisposition := h.privs == adminPrivs |
| 287 | |
| 288 | h.setEtag(digest) |
| 289 | |
| 290 | // Request will be returned with the same content type as is set on the attachment. The caveat to this is if the |
| 291 | // attachment has a content type which is vulnerable to a phishing attack. If this is the case we will return with |
| 292 | // the Content Disposition header so that browsers will download the attachment rather than attempt to render it |
| 293 | // unless overridden by config option. CBG-1004 |
| 294 | contentType, contentTypeSet := meta["content_type"].(string) |
| 295 | if contentTypeSet { |
| 296 | h.setHeader("Content-Type", contentType) |
| 297 | } |
| 298 | |
| 299 | if !h.db.ServeInsecureAttachmentTypes { |
| 300 |
nothing calls this directly
no test coverage detected