Skip to content
This repository has been archived by the owner on Mar 9, 2022. It is now read-only.

Commit

Permalink
Make direct PUT to attachment URL work with streamed request body
Browse files Browse the repository at this point in the history
This case was accidentally not fixed back in commit 7f24896.
Fixes #198.
  • Loading branch information
snej committed Dec 12, 2012
1 parent 8f6ba32 commit d752da8
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 18 deletions.
36 changes: 29 additions & 7 deletions Source/TDRouter+Handlers.m
Expand Up @@ -854,7 +854,10 @@ - (TDStatus) do_DELETE: (TD_Database*)db docID: (NSString*)docID {
} }




- (TDStatus) updateAttachment: (NSString*)attachment docID: (NSString*)docID body: (NSData*)body { - (TDStatus) updateAttachment: (NSString*)attachment
docID: (NSString*)docID
body: (TDBlobStoreWriter*)body
{
TDStatus status; TDStatus status;
TD_Revision* rev = [_db updateAttachment: attachment TD_Revision* rev = [_db updateAttachment: attachment
body: body body: body
Expand All @@ -874,16 +877,35 @@ - (TDStatus) updateAttachment: (NSString*)attachment docID: (NSString*)docID bod




- (TDStatus) do_PUT: (TD_Database*)db docID: (NSString*)docID attachment: (NSString*)attachment { - (TDStatus) do_PUT: (TD_Database*)db docID: (NSString*)docID attachment: (NSString*)attachment {
return [self updateAttachment: attachment TDBlobStoreWriter* blob = db.attachmentWriter;
docID: docID NSInputStream* bodyStream = _request.HTTPBodyStream;
body: (_request.HTTPBody ?: [NSData data])]; if (bodyStream) {
// OPT: Should read this asynchronously
NSMutableData* buffer = [NSMutableData dataWithLength: 32768];
NSInteger bytesRead;
do {
bytesRead = [bodyStream read: buffer.mutableBytes maxLength: buffer.length];
if (bytesRead > 0) {
[blob appendData: [NSData dataWithBytesNoCopy: buffer.mutableBytes
length: bytesRead freeWhenDone: NO]];
}
} while (bytesRead > 0);
if (bytesRead < 0)
return kTDStatusBadAttachment;

} else {
NSData* body = _request.HTTPBody;
if (body)
[blob appendData: body];
}
[blob finish];

return [self updateAttachment: attachment docID: docID body: blob];
} }




- (TDStatus) do_DELETE: (TD_Database*)db docID: (NSString*)docID attachment: (NSString*)attachment { - (TDStatus) do_DELETE: (TD_Database*)db docID: (NSString*)docID attachment: (NSString*)attachment {
return [self updateAttachment: attachment return [self updateAttachment: attachment docID: docID body: nil];
docID: docID
body: nil];
} }




Expand Down
2 changes: 1 addition & 1 deletion Source/TD_Database+Attachments.h
Expand Up @@ -68,7 +68,7 @@ typedef enum {
/** Updates or deletes an attachment, creating a new document revision in the process. /** Updates or deletes an attachment, creating a new document revision in the process.
Used by the PUT / DELETE methods called on attachment URLs. */ Used by the PUT / DELETE methods called on attachment URLs. */
- (TD_Revision*) updateAttachment: (NSString*)filename - (TD_Revision*) updateAttachment: (NSString*)filename
body: (NSData*)body body: (TDBlobStoreWriter*)body
type: (NSString*)contentType type: (NSString*)contentType
encoding: (TDAttachmentEncoding)encoding encoding: (TDAttachmentEncoding)encoding
ofDocID: (NSString*)docID ofDocID: (NSString*)docID
Expand Down
17 changes: 10 additions & 7 deletions Source/TD_Database+Attachments.m
Expand Up @@ -69,6 +69,13 @@ - (void) rememberPendingKey: (TDBlobKey)key forDigest: (NSString*)digest {
} }




- (void) rememberAttachmentWriter: (TDBlobStoreWriter*)writer forDigest:(NSString*)digest {
if (!_pendingAttachmentsByDigest)
_pendingAttachmentsByDigest = [[NSMutableDictionary alloc] init];
_pendingAttachmentsByDigest[digest] = writer;
}


// This is ONLY FOR TESTS (see TDMultipartDownloader.m) // This is ONLY FOR TESTS (see TDMultipartDownloader.m)
#if DEBUG #if DEBUG
- (id) attachmentWriterForAttachment: (NSDictionary*)attachment { - (id) attachmentWriterForAttachment: (NSDictionary*)attachment {
Expand Down Expand Up @@ -561,7 +568,7 @@ - (TDMultipartWriter*) multipartWriterForRevision: (TD_Revision*)rev




- (TD_Revision*) updateAttachment: (NSString*)filename - (TD_Revision*) updateAttachment: (NSString*)filename
body: (NSData*)body body: (TDBlobStoreWriter*)body
type: (NSString*)contentType type: (NSString*)contentType
encoding: (TDAttachmentEncoding)encoding encoding: (TDAttachmentEncoding)encoding
ofDocID: (NSString*)docID ofDocID: (NSString*)docID
Expand Down Expand Up @@ -593,14 +600,10 @@ - (TD_Revision*) updateAttachment: (NSString*)filename
if (!attachments) if (!attachments)
attachments = $mdict(); attachments = $mdict();
if (body) { if (body) {
TDBlobKey key; TDBlobKey key = body.blobKey;
if (![self storeBlob: body creatingKey: &key]) {
*outStatus = kTDStatusAttachmentError;
return nil;
}
NSString* digest = [@"sha1-" stringByAppendingString: [TDBase64 encode: &key NSString* digest = [@"sha1-" stringByAppendingString: [TDBase64 encode: &key
length: sizeof(key)]]; length: sizeof(key)]];
[self rememberPendingKey: key forDigest: digest]; [self rememberAttachmentWriter: body forDigest: digest];
NSString* encodingName = (encoding == kTDAttachmentEncodingGZIP) ? @"gzip" : nil; NSString* encodingName = (encoding == kTDAttachmentEncodingGZIP) ? @"gzip" : nil;
attachments[filename] = $dict({@"digest", digest}, attachments[filename] = $dict({@"digest", digest},
{@"length", @(body.length)}, {@"length", @(body.length)},
Expand Down
21 changes: 18 additions & 3 deletions Source/TD_Database_Tests.m
Expand Up @@ -574,6 +574,14 @@ static void insertAttachment(TD_Database* db, NSData* blob,
} }




static TDBlobStoreWriter* blobForData(TD_Database* db, NSData* data) {
TDBlobStoreWriter* blob = db.attachmentWriter;
[blob appendData: data];
[blob finish];
return blob;
}


TestCase(TD_Database_PutAttachment) { TestCase(TD_Database_PutAttachment) {
RequireTestCase(TD_Database_Attachments); RequireTestCase(TD_Database_Attachments);
// Start with a fresh database in /tmp: // Start with a fresh database in /tmp:
Expand Down Expand Up @@ -607,17 +615,20 @@ static void insertAttachment(TD_Database* db, NSData* blob,


// Update the attachment directly: // Update the attachment directly:
NSData* attachv2 = [@"Replaced body of attach" dataUsingEncoding: NSUTF8StringEncoding]; NSData* attachv2 = [@"Replaced body of attach" dataUsingEncoding: NSUTF8StringEncoding];
[db updateAttachment: @"attach" body: attachv2 type: @"application/foo" [db updateAttachment: @"attach" body: blobForData(db, attachv2)
type: @"application/foo"
encoding: kTDAttachmentEncodingNone encoding: kTDAttachmentEncodingNone
ofDocID: rev1.docID revID: nil ofDocID: rev1.docID revID: nil
status: &status]; status: &status];
CAssertEq(status, kTDStatusConflict); CAssertEq(status, kTDStatusConflict);
[db updateAttachment: @"attach" body: attachv2 type: @"application/foo" [db updateAttachment: @"attach" body: blobForData(db, attachv2)
type: @"application/foo"
encoding: kTDAttachmentEncodingNone encoding: kTDAttachmentEncodingNone
ofDocID: rev1.docID revID: @"1-bogus" ofDocID: rev1.docID revID: @"1-bogus"
status: &status]; status: &status];
CAssertEq(status, kTDStatusConflict); CAssertEq(status, kTDStatusConflict);
TD_Revision* rev2 = [db updateAttachment: @"attach" body: attachv2 type: @"application/foo" TD_Revision* rev2 = [db updateAttachment: @"attach" body: blobForData(db, attachv2)
type: @"application/foo"
encoding: kTDAttachmentEncodingNone encoding: kTDAttachmentEncodingNone
ofDocID: rev1.docID revID: rev1.revID ofDocID: rev1.docID revID: rev1.revID
status: &status]; status: &status];
Expand All @@ -633,6 +644,10 @@ static void insertAttachment(TD_Database* db, NSData* blob,
{@"length", @(23)}, {@"length", @(23)},
{@"stub", $true}, {@"stub", $true},
{@"revpos", @2})})); {@"revpos", @2})}));

NSData* gotAttach = [db getAttachmentForSequence: gotRev2.sequence named: @"attach"
type: NULL encoding: NULL status: &status];
CAssertEqual(gotAttach, attachv2);


// Delete the attachment: // Delete the attachment:
[db updateAttachment: @"nosuchattach" body: nil type: nil [db updateAttachment: @"nosuchattach" body: nil type: nil
Expand Down

0 comments on commit d752da8

Please sign in to comment.