[Cosmo-dev] JSON-RPC considered harmful

Travis Vachon travis at osafoundation.org
Tue Dec 5 18:07:26 PST 2006


Hi folks

I've started design work for bug 7370. For background, please check out:
http://wiki.osafoundation.org/bin/view/Journal/ 
BrianMoseleyCosmoCasualCollaborator (ticket vs. login)
https://bugzilla.osafoundation.org/show_bug.cgi?id=7370
http://wiki.osafoundation.org/bin/view/Journal/ZeroSixTaskBreakdown  
( anonymous access)

The problem is to allow clients (in this case, the PIM ui) read or  
write access to collections based on a ticket id.

Currently, ticketed access to collections relies on information  
presented in the url. For example, if I request /cosmo/collection/ 
{collectionId}?ticket={ticketId}, the TicketAuthenticationProvider  
pulls the collectionId and ticketId out of the url and makes a  
decision to allow access based on this information.

Problem is, the PIM ui uses JSON-RPC, which always makes a request  
to /cosmo/JSON-RPC. This means the collection and ticket information  
would need to be embedded either in a headers or in the JSON content  
body of the request.

There are a couple problems with doing either of these:

headers - we already have the collectionId in the content body. If we  
duplicate this information, we run into problems where a malicious  
user could specify different collectionIds in the header and JSON  
content body. We could work around this, making sure the two match,  
but this would require parsing JSON in the  
TicketAuthenticationProvider. We could also just ignore the  
collectionId in the content body, but this would require some ugly  
retooling of the JSON service. The necessity of having these  also  
begs the question of why we are even using JSON.

JSON content body - this would definitely require parsing the JSON in  
the TicketAuthenticationProvider. If we're ok doing this, this might  
be the most expedient way to get this feature working. That said,  
Bobby and I agree that this isn't a great solution. First, we're  
parsing JSON twice over the course of the request (once in the  
TicketAuthenticationProvider and once in the RPCService). Next, the  
JSON-RPC method signatures wouldn't necessarily guarantee a position  
for the ticket id, so figuring out exactly where in the content body  
the ticket lives would be dicey at best.

Given this, Bobby and I are of the opinion that it would be more  
worth our time to start moving away from JSON-RPC. Leaving the  
current system in place, we would add on the new functionality we  
need by implementing an HTTP based protocol which would return JSON  
identical to the JSON currently returned by the ScoobyService object.

To start (to fix 7370), we would implement the following requests,  
each of which corresponds to a current JSON-RPC method;

getEvent(calendarName, id) -> (GET /item/{itemUid}?ticket={ticketId}
getEvents(calendarPath, beginDate, endDate) -> (GET /collection/ 
{collectionUid}?bDate={beginDate}&eDate={endDate}&ticket={ticketId}
saveEvent(calendarPath, event) -> PUT /item/{collectionUid}/{itemUid}  
w/ JSON item representation as content
removeEvent(calendarPath, event) -> DELETE /item/{itemUid}
getRecurrenceRules(calendarPath, eventIds) -> GET /item/{itemUid}/ 
recurrence?iid={e1}&iid={e2}&...&iid={eN}
saveRecurrenceRule(calendarPath, eventId, recurrenceRule) -> PUT / 
item/{itemUid}/recurrence w/ JSON recurrenceRule representation as  
content
expandEvents(calendarPath, eventIds, utcStartTime, utcEndTime) ->
	GET /collection/{collectionUid}?iid={e1}&iid={e2}&...&iid={eN}&stime= 
{startTime}&etime={endTime}
saveNewEventBreakRecurrence(String calendarPath, event,  
originalEventId, originalEventEndDate) ->
	PUT /breakevent/{originalEventUid}?date=originalEventEndDate w/ JSON  
event as content

You'll notice this scheme also takes into account the work I'm going  
to be doing for bug 7405 (RPC calls by ID not path). I'm probably  
going to fix 7405 before moving ahead with 7370, since it will makes  
things considerably less confusing and prevent duplication of effort.

Finally, you'll notice some of these requests use methods other than  
GET or POST. This is a problem for safari. Google has solved this  
problem in their GData protocol with a new header X-HTTP-Method- 
Override (http://code.google.com/apis/gdata/protocol.html#Updating-an- 
entry). I worked on this idea  a couple months ago after talking with  
BCM, and have a ServletFilter implemented that will provide this  
functionality, it just needs to be checked in.

These would used by any Calendars on the client side that require  
ticket based access. Bobby has a few ideas about the specifics about  
how this should be designed in the short term on the client side, but  
I'd like to leave that for a future e-mail.

We've been talking this through quite a bit today, and would  
definitely like feedback. Thoughts?

Thanks,

Travis


More information about the cosmo-dev mailing list