r11 - 15 Jul 2008 - 08:14:47 - RandyLetnessYou are here: OSAF >  Projects Web  >  CosmoHome > CosmoDevelopmentHome > CosmoMorseCode

Morse Code in Cosmo

Morse Code is the HTTP-based synchronization protocol for Cosmo and Chandler. The goal of the protocol is to efficiently transmit as little information as possible in as few protocol transactions as possible. The protocol is collection-oriented; collections are exposed through the protocol as HTTP resources, but items themselves are not.

General Concepts

Resource Paths

All collection operations are directed to paths of the form /collection/<uid>. In the typical OSAF server deployment of Cosmo, this results in URLs such as http://localhost:8080/cosmo/mc/collection/dc87c5b7-e4eb-431e-a00b-537479e0de47. Requests to paths not of this form result in 404 Not Found responses.

The collection discovery operation is unique in that it addresses a user, not a collection, at the path /user/<username>.

EIMML

Morse code uses EIMML as its data format, which an XML representation of the EIM data format. For more information see:

Synchronization Tokens

Efficient synchronization requires that the server return only the state of items that have changed since the previous synchronization request. In order to know when the client last synchronized and if the collection's "aggregate state" (the state of the collection itself plus that of each member item) has changed, all Morse Code operations (except deletion) return a "sync token" that must be provided by the client on the next synchronization request. Each sync token returned from the server replaces any previous sync token sent from the server.

A sync token is said to be valid if neither the collection nor any of the member items have changed state since the token was issued. Synchronization requests return no data if the provided sync token is found to be valid (although they do return new sync tokens, so that subsequent sync requests only do not have to continuously take into account previously checked periods of time).

Synchronization tokens must also be provided by the client on every update request. If the token is found to be invalid, then another client has updated the collection since this client's last sync, and this client now has stale data and must re-sync it. If the token is valid, then the server proceeds with the update operation.

The sync token is communicated in request and response messages with the X-MorseCode-SyncToken extension header. The token may also be provided for GET and HEAD requests with the token query string parameter; if both the header and parameter are provided, the header value is used in preference).

Example

X-MorseCode-SyncToken: 1163184928488-26779703

Ticket Privileges

When Chandler uses a ticket to access Cosmo with Morse Code, it does not have any idea what privileges the ticket holds. Therefore, when responding to subscribe and synchronize requests, Cosmo includes the X-MorseCode-TicketPrivileges extension header that communicates the privileges of the ticket used to authenticate and authorize the request. The header value is a space-separated list of privileges from the set {read, write, freebusy}.

Examples

X-MorseCode-TicketPrivileges: read
X-MorseCode-TicketPrivileges: read write

Protocol Operations

Discover Collections

Returns an XML document describing the "main" collections in a user's home collection, ignoring any sub-collections.

The document lists the UUID, URL, display name and tickets for each collection following this Relax NG schema. Ticket types are from the set defined in Ticket Privileges. The document also makes use of the XML Base facility to specify a base URI for the collections described in the document.

Status Codes

200 OK
success
403 Not Authorized
the authenticated principal was not authorized to discover the user's collections
404 Not Found
the identified user account was not found

Example

>>> REQUEST <<<
GET /mc/user/bcm HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
>>> RESPONSE <<<
HTTP/1.1 200 OK
Content-Type: text/xml;charset=UTF-8
<?xml version='1.0' encoding='UTF-8'?>
<service xmlns="http://osafoundation.org/mc/" xml:base="http://localhost:8080/cosmo/mc/">
  <collection uuid="6d09302d-4192-4574-a75b-d4fae1b37210" href="collection/6d09302d-4192-4574-a75b-d4fae1b37210">
    <name>Cosmo</name>
    <ticket type="read-only">kfcxuqom00</ticket>
    <ticket type="read-write">prmfu3om10</ticket>
  </collection>
</service>

Publish Collection

Creates a collection identified by the given uid and populates the collection with items as specified in the request payload and returns a sync token that the client should provide on the next synchronize request.

Optionally, the uid of the parent collection for the new collection can be provided in the parent request parameter. If not, the new collection's parent will be the home collection of the user issuing the request. If a ticket is used to authenticate the request, then a parent uid MUST be provided, and the ticket must have write permission for the parent collection.

Publications are atomic; an entire publish operation fails if any single item cannot be saved. The collection is not considered by the server to exist (for the purpose of fulfilling other Morse Code requests) until the publish operation has completed.

Status Codes

201 Created
success
400 Bad Request
a parent uid was not provided for a non-user authentication principal
403 Not Authorized
the authenticated principal was not authorized to update an item (see response for details)
404 Not Found
the identified parent collection does not exist in storage
409 Conflict
the provided uid for the new collection is already in use, or multiple records specify the same iCalendar uid
412 Precondition Failed
the identified parent item is not a collection

Example
This example shows a successful publish operation:

>>> REQUEST <<<
PUT /mc/collection/cafebebe-deadbeef?parent=dc87c5b7-e4eb-431e-a00b-537479e0de47 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... item states follow
>>> RESPONSE <<<
HTTP/1.1 201 Created
X-MorseCode-SyncToken: 1163186570770-7684996

This example shows a publish containing a record with a uuid that the request is not authorized for:

>>> REQUEST <<<
POST /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18?token=1163185720879-11797571 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
X-MorseCode-SyncToken: 1163186570770-7684996
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... record set with uuid d6d60462-f329-49ce-a91b-afc1641cb132 follows
HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
X-Cosmo-Version: 0.13-SNAPSHOT
Content-Type: application/xml
Content-Length: 276
Date: Mon, 10 Mar 2008 15:55:51 GMT
<?xml version='1.0' encoding='UTF-8'?>
<mc:error xmlns:mc="http://osafoundation.org/mc/">
  <mc:insufficient-privileges>
    <mc:target-uuid>d6d60462-f329-49ce-a91b-afc1641cb132</mc:target-uuid>
    <mc:required-privilege>READ</mc:required-privilege>
  </mc:insufficient-privileges>
</mc:error>

This example shows a publish where the collection already exists:

>>> REQUEST <<<
POST /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18?token=1163185720879-11797571 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
X-MorseCode-SyncToken: 1163186570770-7684996
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... record set follows
HTTP/1.1 409 Conflict
Server: Apache-Coyote/1.1
X-Cosmo-Version: 0.13-SNAPSHOT
Content-Type: application/xml
Content-Length: 276
Date: Mon, 10 Mar 2008 15:55:51 GMT
<?xml version='1.0' encoding='UTF-8'?>
<mc:error xmlns:mc="http://osafoundation.org/mc/">
  <mc:collection-exists>
    <mc:existing-uuid>517c9bb6-844d-4b42-9e95-06b18a44220f</mc:existing-uuid>
  </mc:collection-exists>
</mc:error>

Update Collection

Updates the state of certain member items of the collection (and potentially the state of the collection itself) as specified in the request payload and returns a sync token that the client should provide on the next synchronization request.

The sync token is specified in the request with the X-MorseCode-SyncToken header. This header is required.

The client must send the complete state of each item to be updated. Failure to do so may (but is not required to) result in the server removing any previously stored state for an item that was not included in the update being processed.

Updates are atomic; an entire update operation fails if any single item cannot be saved with its new state.

The collection is implicitly locked at the beginning of the update operation. While the update is in process, if the server receives another update request, it must reject that request. When the update operation is complete, the collection is unlocked and the server may accept another update request.

Status Codes

204 No Content
success
205 Reset Content
the collection has been updated since the provided synchronization token was generated, and the client must re-synchronize
400 Bad Request
no synchronization token was provided, or the token is malformed
403 Not Authorized
the authenticated principal was not authorized to update an item (see response for details)
404 Not Found
the identified collection does not exist in storage
409 Conflict
a published record contains an iCalendar uid that is already in use by an existing item in the collection
412 Precondition Failed
the identified item is not a collection
423 Locked
the collection is locked for an in-progress update

Examples

This example shows a successful update operation.

>>> REQUEST <<<
POST /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18?token=1163185720879-11797571 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
X-MorseCode-SyncToken: 1163186570770-7684996
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... item states follow
>>> RESPONSE <<<
HTTP/1.1 204 No Content
X-MorseCode-SyncToken: 1163186570770-7684996

This example shows an update containing a record that specifies an iCalendar uid that is already in use by an existing item in the collection.

>>> REQUEST <<<
POST /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18?token=1163185720879-11797571 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
X-MorseCode-SyncToken: 1163186570770-7684996
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... record set with uuid ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj follows
>>> RESPONSE <<<
HTTP/1.1 409 icalUid xyz already in use for collection 4c23d480-8e2a-43f3-adff-c460adfe4a18
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <no-uid-conflict>
    <existing-uuid>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</existing-uuid>
    <conflicting-uuid>ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj</conflicting-uuid>
  </no-uid-conflict>
</error>

This example shows an update containing a record with a uuid that the request is not authorized for

>>> REQUEST <<<
POST /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18?token=1163185720879-11797571 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
X-MorseCode-SyncToken: 1163186570770-7684996
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... record set with uuid d6d60462-f329-49ce-a91b-afc1641cb132 follows
HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
X-Cosmo-Version: 0.13-SNAPSHOT
Content-Type: application/xml
Content-Length: 276
Date: Mon, 10 Mar 2008 15:55:51 GMT
<?xml version='1.0' encoding='UTF-8'?>
<mc:error xmlns:mc="http://osafoundation.org/mc/">
  <mc:insufficient-privileges>
    <mc:target-uuid>d6d60462-f329-49ce-a91b-afc1641cb132</mc:target-uuid>
    <mc:required-privilege>READ</mc:required-privilege>
  </mc:insufficient-privileges>
</mc:error>

Subscribe to Collection

Returns the state of the identified collection and of all contained items (excluding subcollections) and a synchronization token that the client should provide on the next synchronization request.

Status Codes

200 OK
success
404 Not Found
the identified collection does not exist in storage
412 Precondition Failed
the identified item is not a collection

Example

>>> REQUEST <<<
GET /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
>>> RESPONSE <<<
HTTP/1.1 200 OK
X-MorseCode-SyncToken: 1163184928488-26779703
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... item states follow ...

Synchronize Collection

Returns the complete state of any member items of the identified collection (excluding subcollections) that have changed since the time that the provided synchronization token was valid (and possibly the state of the collection itself, if it has changed), and a synchronization token that the client should provide on the next synchronization request.

The sync token is specified in the request with the token parameter. This parameter is required (if not provided, the request will be interpreted as a subscribe).

Status Codes

200 OK
success
400 Bad Request
the provided synchronization token is malformed
404 Not Found
the identified collection does not exist in storage
412 Precondition Failed
the identified item is not a collection

Example

>>> REQUEST <<<
GET /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18?token=1163185720879-11797571 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
>>> RESPONSE <<<
HTTP/1.1 200 OK
X-MorseCode-SyncToken: 1163185735535-10665237
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... item states follow ...

Delete Collection

Signifies that the indicated collection is to be removed from storage as well as all contained items. If a contained item is a member of multiple collections, it is not removed from storage, just from the deleted collection. All items are guaranteed to be removed before the response is returned.

Status Codes

204 No Content
success
404 Not Found
the identified collection does not exist in storage
412 Precondition Failed
the identified item is not a collection

Example

>>> REQUEST <<<
DELETE /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
>>> RESPONSE <<<
HTTP/1.1 204 No Content

Error Handling

Many things can cause a 400 (Bad Request) and in some cases 500 (server error). Cosmo does its best to include detailed error information in the form of an XML response. Clients should expect these kinds of errors:

icalUid in use

This happens when an item with icalUid A is added to a collection that contains another item with icalUid A. The server doesn't allow this as icalUid must be unique within a collection.
>>> RESPONSE <<<
HTTP/1.1 409 icalUid xyz already in use for collection 4c23d480-8e2a-43f3-adff-c460adfe4a18
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <no-uid-conflict>
    <existing-uuid>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</existing-uuid>
    <conflicting-uuid>ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj</conflicting-uuid>
  </no-uid-conflict>
</error>

data-validation error

This happens for several reasons. For example if a modification is added without a master, or if an item is deleted that doesn't exist. A message and item uuid are included in the response.
>>> RESPONSE <<<
HTTP/1.1 400
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <data-validation-error>
    <item-uuid>ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj</item-uuid>
    <message>aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee</message>
  </data-validation-error>
</error>

bad-request error

This happens for several reasons also and is the generic version of the data-validation-error. Only a message is included.
>>> RESPONSE <<<
HTTP/1.1 400
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <bad-request-error>
    this was a bad request because...
  </bad-request-error>
</error>

collection exists error

This happens during a PUT, when the collection already exists.
>>> RESPONSE <<<
HTTP/1.1 409
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <collection-exists>
    <existing-uuid>ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj</existing-uuid>
  </collection-exists>
</error>

not collection error

This happens when the target collection uuid exists, but is not a collection.
>>> RESPONSE <<<
HTTP/1.1 412
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <not-collection>
    <target-uuid>ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj</target-uuid>
  </not-collection>
</error>

unknown collection error

This happens when the collection uuid doesn't exist.
>>> RESPONSE <<<
HTTP/1.1 404
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <unknown-collection>
    <collection-uuid>ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj</collection-uuid>
  </unknown-collection>
</error>

sync token error

This happens when the provided sync-token is invalid
>>> RESPONSE <<<
HTTP/1.1 400
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <invalid-synctoken>
    <token>blah</token>
  </invalid-synctoken>
</error>

unknown user error

This happens when a user document specifies an unknown user
>>> RESPONSE <<<
HTTP/1.1 404
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <unknown-user>
    <username>fff</username>
  </unknown-user>
</error>

server error

This happens when something goes wrong on the server.
>>> RESPONSE <<<
HTTP/1.1 500
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<error xmlns="http://osafoundation.org/mc/">
  <internal-server-error>
    the server failed because...
  </internal-server-error>
</error>

Security Considerations

Cosmo supports Basic and ticket authentication for Morse Code.

Basic

When Basic authentication is used, the authenticated user may publish collections as children of his home collection and any other collection of which he is the owner. He may update, subscribe to, synchronize, and delete any collection that he owns.

Tickets

Tickets are accepted for all Morse Code operations (with a caveat for publishing a collection - see above). The ticket must confer the appropriate permission for the operation (read for subscribe and synchronize, write for publish, update and delete). When a collection or item is created as the result of a ticket-authenticated request, the owner of the ticket becomes the owner of the new item.

It is possible to authenticate as a ticket or user and include extra tickets in a publish/update request. This is accomplished by including any number of X-MorseCode-Ticket request headers containing the ticket key(s). For example:

>>> REQUEST <<<
POST /mc/collection/4c23d480-8e2a-43f3-adff-c460adfe4a18?token=1163185720879-11797571 HTTP/1.1
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
X-MorseCode-SyncToken: 1163186570770-7684996
X-MorseCode-Ticket: ticketkey1
X-MorseCode-Ticket: ticketkey2
X-MorseCode-Ticket: ticketkey3, ticketkey4, ticketkey5
Content-Length: xxx
Content-Type: application/eim+xml; charset=UTF-8
... record set with uuid ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj follows

In this example, a request is authenticated as a user and includes 5 tickets, which gives the user access to all items the user has access to plus any items that the tickets grant access to. If a request isn't authorized to update an item, a 403 response will be returned, with an error message including the item uuid that requires authorization and the privilege required. For example:

HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
X-Cosmo-Version: 0.13-SNAPSHOT
Content-Type: application/xml
Content-Length: 276
Date: Mon, 10 Mar 2008 15:55:51 GMT
<?xml version='1.0' encoding='UTF-8'?>
<mc:error xmlns:mc="http://osafoundation.org/mc/">
  <mc:insufficient-privileges>
    <mc:target-uuid>d6d60462-f329-49ce-a91b-afc1641cb132</mc:target-uuid>
    <mc:required-privilege>READ</mc:required-privilege>
  </mc:insufficient-privileges>
</mc:error>

This response indicates that the request was not authorized to read the item with uuid d6d60462-f329-49ce-a91b-afc1641cb132. The item uuid could indicate a collection item or child item. It is up to the client to give the user more details such as item type and item name.

Changes

March 28, 2008

  • Added error handling section containing what errors can occur and response formats

March 10, 2008

  • Added example publish/update with insufficient privileges
  • Updated security considerations with info on how to include extra tickets

May 7, 2007

  • Added "Discover Collections" section
  • Updated "resource paths" section to describe user paths
  • Retitled sections
  • Clarified deletion of collections with regard to items that belong to multiple collections
  • Updated exampls to include /mc protocol selector in path and to remove non-essential headers

Mar 23, 2007

  • Added TOC
  • Added "Ticket Privileges" section describing the X-MorseCode-TicketPrivileges extension header for subscribe and synchronize responses

Nov 20, 2006

  • Added the requirement that update requests provide a sync token.
  • Allowed request messages to contain a sync token in the X-MorseCode-SyncToken extension header, overriding any provided in the request's query string, and modified the update protocol example to show this.
  • Clarified that the client must provide the complete state of each item to be modified in an update request.
  • Added response code 205 Reset Content for update requests when the targeted collection has been updated by another client since the first client's sync token was generated.

Nov 10, 2006

Initial draft.

Edit | WYSIWYG | Attach | Printable | Raw View | Backlinks: Web, All Webs | History: r11 < r10 < r9 < r8 < r7 | More topic actions
 
Open Source Applications Foundation
Except where otherwise noted, this site and its content are licensed by OSAF under an Creative Commons License, Attribution Only 3.0.
See list of page contributors for attributions.