| < draft-ietf-jmap-blob-10.txt | draft-ietf-jmap-blob-11.txt > | |||
|---|---|---|---|---|
| JMAP B. Gondwana, Ed. | JMAP B. Gondwana, Ed. | |||
| Internet-Draft Fastmail | Internet-Draft Fastmail | |||
| Updates: 8620 (if approved) 19 March 2022 | Updates: 8620 (if approved) 26 March 2022 | |||
| Intended status: Standards Track | Intended status: Standards Track | |||
| Expires: 20 September 2022 | Expires: 27 September 2022 | |||
| JMAP Blob management extension | JMAP Blob management extension | |||
| draft-ietf-jmap-blob-10 | draft-ietf-jmap-blob-11 | |||
| Abstract | Abstract | |||
| The JMAP base protocol (RFC8620) provides the ability to upload and | The JMAP base protocol (RFC8620) provides the ability to upload and | |||
| download arbitrary binary data via HTTP POST and GET on defined | download arbitrary binary data via HTTP POST and GET on defined | |||
| endpoint. This binary data is called a "blob". | endpoint. This binary data is called a "blob". | |||
| This extension adds additional ways to create and access blobs, by | This extension adds additional ways to create and access blobs, by | |||
| making inline method calls within a standard JMAP request. | making inline method calls within a standard JMAP request. | |||
| skipping to change at page 1, line 39 ¶ | skipping to change at page 1, line 39 ¶ | |||
| Internet-Drafts are working documents of the Internet Engineering | Internet-Drafts are working documents of the Internet Engineering | |||
| Task Force (IETF). Note that other groups may also distribute | Task Force (IETF). Note that other groups may also distribute | |||
| working documents as Internet-Drafts. The list of current Internet- | working documents as Internet-Drafts. The list of current Internet- | |||
| Drafts is at https://datatracker.ietf.org/drafts/current/. | Drafts is at https://datatracker.ietf.org/drafts/current/. | |||
| Internet-Drafts are draft documents valid for a maximum of six months | Internet-Drafts are draft documents valid for a maximum of six months | |||
| and may be updated, replaced, or obsoleted by other documents at any | and may be updated, replaced, or obsoleted by other documents at any | |||
| time. It is inappropriate to use Internet-Drafts as reference | time. It is inappropriate to use Internet-Drafts as reference | |||
| material or to cite them other than as "work in progress." | material or to cite them other than as "work in progress." | |||
| This Internet-Draft will expire on 20 September 2022. | This Internet-Draft will expire on 27 September 2022. | |||
| Copyright Notice | Copyright Notice | |||
| Copyright (c) 2022 IETF Trust and the persons identified as the | Copyright (c) 2022 IETF Trust and the persons identified as the | |||
| document authors. All rights reserved. | document authors. All rights reserved. | |||
| This document is subject to BCP 78 and the IETF Trust's Legal | This document is subject to BCP 78 and the IETF Trust's Legal | |||
| Provisions Relating to IETF Documents (https://trustee.ietf.org/ | Provisions Relating to IETF Documents (https://trustee.ietf.org/ | |||
| license-info) in effect on the date of publication of this document. | license-info) in effect on the date of publication of this document. | |||
| Please review these documents carefully, as they describe your rights | Please review these documents carefully, as they describe your rights | |||
| skipping to change at page 2, line 21 ¶ | skipping to change at page 2, line 21 ¶ | |||
| 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 | 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 2 | |||
| 2. Conventions Used In This Document . . . . . . . . . . . . . . 3 | 2. Conventions Used In This Document . . . . . . . . . . . . . . 3 | |||
| 3. Addition to the Capabilities Object . . . . . . . . . . . . . 3 | 3. Addition to the Capabilities Object . . . . . . . . . . . . . 3 | |||
| 3.1. urn:ietf:params:jmap:blob . . . . . . . . . . . . . . . . 3 | 3.1. urn:ietf:params:jmap:blob . . . . . . . . . . . . . . . . 3 | |||
| 3.1.1. Capability Example . . . . . . . . . . . . . . . . . 4 | 3.1.1. Capability Example . . . . . . . . . . . . . . . . . 4 | |||
| 4. Blob Methods . . . . . . . . . . . . . . . . . . . . . . . . 4 | 4. Blob Methods . . . . . . . . . . . . . . . . . . . . . . . . 4 | |||
| 4.1. Blob/upload . . . . . . . . . . . . . . . . . . . . . . . 5 | 4.1. Blob/upload . . . . . . . . . . . . . . . . . . . . . . . 5 | |||
| 4.1.1. Blob/upload simple example . . . . . . . . . . . . . 7 | 4.1.1. Blob/upload simple example . . . . . . . . . . . . . 7 | |||
| 4.1.2. Blob/upload complex example . . . . . . . . . . . . . 8 | 4.1.2. Blob/upload complex example . . . . . . . . . . . . . 8 | |||
| 4.2. Blob/get . . . . . . . . . . . . . . . . . . . . . . . . 11 | 4.2. Blob/get . . . . . . . . . . . . . . . . . . . . . . . . 11 | |||
| 4.2.1. Blob/get simple example . . . . . . . . . . . . . . . 12 | 4.2.1. Blob/get simple example . . . . . . . . . . . . . . . 13 | |||
| 4.2.2. Blob/get example with range and encoding errors . . . 13 | 4.2.2. Blob/get example with range and encoding errors . . . 14 | |||
| 4.3. Blob/lookup . . . . . . . . . . . . . . . . . . . . . . . 19 | 4.3. Blob/lookup . . . . . . . . . . . . . . . . . . . . . . . 20 | |||
| 4.3.1. Blob/lookup example . . . . . . . . . . . . . . . . . 20 | 4.3.1. Blob/lookup example . . . . . . . . . . . . . . . . . 21 | |||
| 5. Security considerations . . . . . . . . . . . . . . . . . . . 22 | 5. Security considerations . . . . . . . . . . . . . . . . . . . 23 | |||
| 6. IANA considerations . . . . . . . . . . . . . . . . . . . . . 22 | 6. IANA considerations . . . . . . . . . . . . . . . . . . . . . 23 | |||
| 6.1. JMAP Capability registration for "blob" . . . . . . . . . 22 | 6.1. JMAP Capability registration for "blob" . . . . . . . . . 23 | |||
| 6.2. JMAP Error Codes Registration for "unknownDataType" . . . 23 | 6.2. JMAP Error Codes Registration for "unknownDataType" . . . 24 | |||
| 6.3. Creation of "JMAP Data Types" Registry . . . . . . . . . 23 | 6.3. Creation of "JMAP Data Types" Registry . . . . . . . . . 24 | |||
| 7. Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 | 7. Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 | |||
| 8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 27 | 8. Acknowledgements . . . . . . . . . . . . . . . . . . . . . . 28 | |||
| 9. Normative References . . . . . . . . . . . . . . . . . . . . 27 | 9. Normative References . . . . . . . . . . . . . . . . . . . . 28 | |||
| 10. Informative References . . . . . . . . . . . . . . . . . . . 27 | 10. Informative References . . . . . . . . . . . . . . . . . . . 28 | |||
| Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 28 | Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 29 | |||
| 1. Introduction | 1. Introduction | |||
| Sometimes JMAP ([RFC8620]) interactions require creating a blob and | Sometimes JMAP ([RFC8620]) interactions require creating a blob and | |||
| then referencing it. In the same way that IMAP Literals were | then referencing it. In the same way that IMAP Literals were | |||
| extended by [RFC7888], embedding small blobs directly into the JMAP | extended by [RFC7888], embedding small blobs directly into the JMAP | |||
| method calls array can be an option for reducing roundtrips. | method calls array can be an option for reducing roundtrips. | |||
| Likewise, when fetching an object, it can be useful to also fetch the | Likewise, when fetching an object, it can be useful to also fetch the | |||
| raw content of that object without a separate roundtrip. | raw content of that object without a separate roundtrip. | |||
| skipping to change at page 12, line 46 ¶ | skipping to change at page 12, line 46 ¶ | |||
| value MUST be null. In the case where data was requested and the | value MUST be null. In the case where data was requested and the | |||
| data is not valid UTF-8, then data:asBase64 MUST be returned. | data is not valid UTF-8, then data:asBase64 MUST be returned. | |||
| If the selected range requests data outside the blob (i.e. the | If the selected range requests data outside the blob (i.e. the | |||
| offset+length is larger than the blob) then the result is either just | offset+length is larger than the blob) then the result is either just | |||
| the octets from the offset to the end of the blob, or an empty string | the octets from the offset to the end of the blob, or an empty string | |||
| if the offset is past the end of the blob. Either way, the | if the offset is past the end of the blob. Either way, the | |||
| isTruncated property in the result MUST be set to true to tell the | isTruncated property in the result MUST be set to true to tell the | |||
| client that the requested range could not be fully satisfied. | client that the requested range could not be fully satisfied. | |||
| Servers SHOULD store the size for blobs in a format which is | ||||
| efficient to read, and clients SHOULD limit their request to just the | ||||
| size parameter if that is all they need, as fetching blob content | ||||
| could be significantly more expensive and slower for the server. | ||||
| 4.2.1. Blob/get simple example | 4.2.1. Blob/get simple example | |||
| Where a blob containing the string "The quick brown fox jumped over | Where a blob containing the string "The quick brown fox jumped over | |||
| the lazy dog!" has blobId G6ec94756e3e046be78fcb33953b85b944e70673e. | the lazy dog!" has blobId G6ec94756e3e046be78fcb33953b85b944e70673e. | |||
| Method Call: | The first method call requests just the size for multiple blobs, and | |||
| the second requests both size and a short range of the data for one | ||||
| of the blobs. | ||||
| Method Calls: | ||||
| [ | [ | |||
| "Blob/get", | [ | |||
| { | "Blob/get", | |||
| "accountId" : "account1", | { | |||
| "ids" : [ | "ids" : [ | |||
| "G6ec94756e3e046be78fcb33953b85b944e70673e", | "G6ec94756e3e046be78fcb33953b85b944e70673e", | |||
| "not-a-blob" | "not-a-blob" | |||
| ], | ], | |||
| "properties" : [ | "properties" : [ | |||
| "data:asText", | "size" | |||
| "data:asBase64", | ] | |||
| "size" | }, | |||
| ], | "R1" | |||
| "offset" : 4, | ], | |||
| "length" : 9 | [ | |||
| }, | "Blob/get", | |||
| "R1" | { | |||
| "accountId" : "account1", | ||||
| "ids" : [ | ||||
| "G6ec94756e3e046be78fcb33953b85b944e70673e" | ||||
| ], | ||||
| "properties" : [ | ||||
| "data:asText", | ||||
| "data:asBase64", | ||||
| "size" | ||||
| ], | ||||
| "offset" : 4, | ||||
| "length" : 9 | ||||
| }, | ||||
| "R2" | ||||
| ] | ||||
| ] | ] | |||
| Response: | Responses: | |||
| [ | [ | |||
| "Blob/get", | [ | |||
| { | "Blob/get", | |||
| "accountId": "account1", | { | |||
| "list": [ | "accountId": "account1", | |||
| { | "list": [ | |||
| "id": "G6ec94756e3e046be78fcb33953b85b944e70673e", | { | |||
| "data:asText": "quick bro", | "id": "G6ec94756e3e046be78fcb33953b85b944e70673e", | |||
| "data:asBase64": "cXVpY2sgYnJvCg==", | "size": 46 | |||
| "size": 46 | } | |||
| } | ], | |||
| ], | "notFound": [ | |||
| "notFound": [ | "not-a-blob" | |||
| "not-a-blob" | ] | |||
| ] | }, | |||
| }, | "R1" | |||
| "R1" | ], | |||
| [ | ||||
| "Blob/get", | ||||
| { | ||||
| "accountId": "account1", | ||||
| "list": [ | ||||
| { | ||||
| "id": "G6ec94756e3e046be78fcb33953b85b944e70673e", | ||||
| "data:asText": "quick bro", | ||||
| "data:asBase64": "cXVpY2sgYnJvCg==", | ||||
| "size": 46 | ||||
| } | ||||
| ] | ||||
| }, | ||||
| "R2" | ||||
| ] | ||||
| ] | ] | |||
| 4.2.2. Blob/get example with range and encoding errors | 4.2.2. Blob/get example with range and encoding errors | |||
| The b1 value is the text: "The quick brown fox jumped over the | The b1 value is the text: "The quick brown fox jumped over the | |||
| \x81\x81 fox" which contains an invalid utf8 sequence. | \x81\x81 fox" which contains an invalid utf8 sequence. | |||
| The results have the following interesting properties: | The results have the following interesting properties: | |||
| * G1: defaults to data and size - so b1 returns isEncodingProblem | * G1: defaults to data and size - so b1 returns isEncodingProblem | |||
| skipping to change at page 24, line 45 ¶ | skipping to change at page 25, line 45 ¶ | |||
| Table 1 | Table 1 | |||
| 7. Changes | 7. Changes | |||
| EDITOR: please remove this section before publication. | EDITOR: please remove this section before publication. | |||
| The source of this document exists on github at: | The source of this document exists on github at: | |||
| https://github.com/brong/draft-gondwana-jmap-blob/ | https://github.com/brong/draft-gondwana-jmap-blob/ | |||
| (https://github.com/brong/draft-gondwana-jmap-blob/) | (https://github.com/brong/draft-gondwana-jmap-blob/) | |||
| *draft-ietf-jmap-blob-11*: | ||||
| * updates based on IETF113 feedback: | ||||
| - added wording to suggest the a Blob/get of just size might be | ||||
| faster | ||||
| - added an example with just the size field being selected | ||||
| *draft-ietf-jmap-blob-10*: | *draft-ietf-jmap-blob-10*: | |||
| * removed remaining references to catenate. | * removed remaining references to catenate. | |||
| *draft-ietf-jmap-blob-09*: | *draft-ietf-jmap-blob-09*: | |||
| * tidied up introduction text | * tidied up introduction text | |||
| * replaced Blob/set with Blob/upload | * replaced Blob/set with Blob/upload | |||
| * made all upload creates take an array of sources to normalise | * made all upload creates take an array of sources to normalise | |||
| behaviour at the cost of a slightly more complex default case. | behaviour at the cost of a slightly more complex default case. | |||
| *draft-ietf-jmap-blob-08*: | *draft-ietf-jmap-blob-08*: | |||
| * Fixed spelling of Neil's name in acknowledgements | * Fixed spelling of Neil's name in acknowledgements | |||
| * Last call review (thanks Jim Fenton) | * Last call review (thanks Jim Fenton) | |||
| End of changes. 12 change blocks. | ||||
| 52 lines changed or deleted | 100 lines changed or added | |||
This html diff was produced by rfcdiff 1.48. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ | ||||