MCPcopy Create free account
hub / github.com/couchbase/sync_gateway / ReadMultipartDocument

Function ReadMultipartDocument

rest/multipart.go:216–304  ·  view source on GitHub ↗
(reader *multipart.Reader)

Source from the content-addressed store, hash-verified

214}
215
216func ReadMultipartDocument(reader *multipart.Reader) (db.Body, error) {
217 // First read the main JSON document body:
218 mainPart, err := reader.NextPart()
219 if err != nil {
220 return nil, err
221 }
222 var body db.Body
223 err = ReadJSONFromMIME(http.Header(mainPart.Header), mainPart, &body)
224 if err != nil {
225 return nil, err
226 }
227
228 // Collect the attachments with a "follows" property, which will appear as MIME parts:
229 followingAttachments := map[string]map[string]interface{}{}
230 for name, value := range db.GetBodyAttachments(body) {
231 if meta := value.(map[string]interface{}); meta["follows"] == true {
232 followingAttachments[name] = meta
233 }
234 }
235
236 // Subroutine to look up a following attachment given its digest. (I used to pre-compute a
237 // map from digest->name, which was faster, but that broke down if there were multiple
238 // attachments with the same contents! See #96)
239 findFollowingAttachment := func(withDigest string) (string, map[string]interface{}) {
240 for name, meta := range followingAttachments {
241 if meta["follows"] == true {
242 if digest, ok := meta["digest"].(string); ok && digest == withDigest {
243 return name, meta
244 }
245 }
246 }
247 return "", nil
248 }
249
250 // Read the parts one by one:
251 for i := 0; i < len(followingAttachments); i++ {
252 part, err := reader.NextPart()
253 if err != nil {
254 if err == io.EOF {
255 err = base.HTTPErrorf(http.StatusBadRequest,
256 "Too few MIME parts: expected %d attachments, got %d",
257 len(followingAttachments), i)
258 }
259 return nil, err
260 }
261 data, err := io.ReadAll(part)
262 _ = part.Close()
263 if err != nil {
264 return nil, err
265 }
266
267 // Look up the attachment by its digest:
268 digest := db.Sha1DigestKey(data)
269 name, meta := findFollowingAttachment(digest)
270 if meta == nil {
271 name, meta = findFollowingAttachment(md5DigestKey(data))
272 if meta == nil {
273 return nil, base.HTTPErrorf(http.StatusBadRequest,

Callers 1

readDocumentMethod · 0.85

Calls 8

GetBodyAttachmentsFunction · 0.92
HTTPErrorfFunction · 0.92
Sha1DigestKeyFunction · 0.92
ToInt64Function · 0.92
ReadJSONFromMIMEFunction · 0.85
md5DigestKeyFunction · 0.85
HeaderMethod · 0.80
CloseMethod · 0.65

Tested by

no test coverage detected