--
John Panzer (http://abstractioneer.org)
+1. No reason we should have two specs doing the exact same thing differently. The fact it was pretty simple to get this done only proves the point.
EHL
+1 – all for interoperability =)
From:
opensocial-an...@googlegroups.com [mailto:opensocial-an...@googlegroups.com]
On Behalf Of Ben Metcalfe
Sent: Monday, July 28, 2008 2:29 PM
To: opensocial-an...@googlegroups.com
Subject: Re: Align OpenSocial RESTful API with PortableContacts
+ 1 from me too, I think this is a great idea – really helps us with where we can take Data Availability too.
A general +1 but we need to break out the specific proposals. Here are the comments from MySpace on the details:
http://docs.google.com/Doc?docid=dfxpm7m8_4gfsgs6g2&hl=en
~Paul
From: opensocial-an...@googlegroups.com
[mailto:opensocial-an...@googlegroups.com] On Behalf Of Ben
Metcalfe
Sent: Monday, July 28, 2008 2:29 PM
To: opensocial-an...@googlegroups.com
Subject: Re: Align OpenSocial RESTful API with PortableContacts
+ 1 from me too, I think this is a great idea – really helps us with where we can take Data Availability too.
Additionally, while the concept of enveloping the semantics and response format of Portable Contacts into the OS REST API obviously has big support for good reason, there needs to be a way for the consumer to differentiate a request for Friends and a request for Contacts as the security policies and available data may be different accordingly. A relationship on a social network does not imply that the users are granted access to each other’s contact info, let alone allowed to make it available to a 3rd party consumer.
This is simple enough if we include another grouping of @contacts on people.
~Paul
- Change support for JSON-P from MAY to MUST for read-only (GET) requests (section 3).
JSONP (GET with callback) is a useful and commonly available capability, especially for APIs that return JSON format. It is also appropriately secure for providers, certainly when accessing public data (as described in section 4), and also when accessing protected data, provided the GET URL is signed with OAuth parameters in the query string. Consumers that want to keep their Consumer Secret and/or Access Secret hidden from users can still sign JSONP requests by sending an XHR to their own servers that returns a signed URL and then using that URL for the JSONP call. If JSONP support is not required, consumers must effectively assume is it not generally available. Note that OAuth requests contain a nonce and timestamp and are thus not replayable, so it is still secure to make client-side OAuth requests via JSON-P.
- Add a status element to the response, containing the sub-fields code={num} and reason={string} that indicates the status of the response.
When making a request via JSON-P, the Consumer does not have access to the HTTP status codes, so the response status needs to be part of the response JSON itself. This is also very useful in other situations, such as when developers enter a request URL into a web browser to see the results (since HTTP status codes are not normally shown in a web browser), or when using a simple invocation of curl, which returns the response body as its response. The proposed code and reason sub-fields of the status will mirror the HTTP status code and reason, and also serve to accommodate Providers that can not easily modify HTTP response headers (just as some sites find it easier to display error pages with an HTTP 200 status as normal web pages). For Consumers to interpret the response unambiguously, if the HTTP status code is NOT 200, it is the authoritative value, and the status code returned in the body SHOULD NOT differ from it. However, if the HTTP status code is 200, the status code returned in the body is the authoritative value.
In OpenSocial, when updating or creating, you're often slinging around individual entries (not collections) and I think that forcing those into collections would be weird. I also think that getting your own profile back in an array of length 1 is just a bit weird. It's valuable and useful to be able to send back what you get -- in other words, if someone using curl does a GET, they should be able to PUT it back with updates and it should work. A PUT of a collection to one's own profile record is strange.
- Standardize that all responses SHALL have the same structure, namely: a set of response meta-data fields and a collection of entries (section 2).
Currently the structure of responses differs depending on whether the request is for a list of people or for a single specific person. In the former case, there is space for meta-data fields like author, status, totalResults, and so on, whereas when returning a single item, the contact schema fields themselves are returned at the top level, leaving no room for response meta-data, and requiring Consumers to parse these responses differently. We believe that having two response formats adds unnecessary complexity, and hinders the ability of Providers to specify meta-data about the response to requests for individual items. For instance, there is currently no way for Providers to indicate response status to JSON-P requests for individual contacts. We propose that the JSON representation of all responses contain an entry array in which the response entries reside. This way, requests for individual entries and requests for multiple entries that happen to return a single result would be treated identically. This is also easily kept in alignment with the AtomPub-to-JSON mapping rules described in section 2: in cases where a single <entry> would be returned instead of a <feed>, the JSON structure can be kept the same, and that single <entry> is the single child of the entry array (i.e. equivalent to a feed containing one entry). Note also that when POSTing updated contact information for a person, it is still correct to post the contact info directly; this standardization only applies to responses.
I don't feel strongly about arrays vs. single results per se, but I do feel strongly about not surprising the user and about minimizing the amount of code they need to write. When making normal people requests with opensocial, my understanding is you'll always get back an array of entries, which sometimes might contain only one entry. But when using the URL-selector syntax to request a specific person, you'll just get the raw data of that person in the top-level field, which I find surprising and inconsistent, and which is missing an envelope.
So if you want to add an envelope, and you want to treat requests for individual people separately, and you don't want to return an array if you know in advance there will only be one result, what format do you propose? We could make "entry" the name of the single contact, rather than the array of objects, but that just makes me worried that consumers will have to test the type of value of "entry" before they process it, which I think is a worse sin than always retuning an array of contacts, even when you know it will only contain one entry.
Cassie-I think you've convinced me to go with your hybrid proposal for names: a required, top-level "displayName" field, and also a singular "name" bundle with sub-fields for each component of the name, and a formatted full name field. I would suggest you rename name.unstructured to name.formatted to be consistent with address.formatted (and for the same semantic reasons), but otherwise I'm fine with this. It means we still have a single, top-level field to label the contact that everyone can easily find and use, and it's clear that lots of people felt at least intuitively that keeping the name fields bundled is "cleaner", even though it adds intermediate structure on the wire for a single field.
I’m against returning a 200 in the status but still needing to look for error codes in the response.
If everything went fine, return a 200.
If things went badly and the “thing” is controllable by the client, return a 400 (The request had bad syntax or was inherently impossible to be satisfied). In the 400 case, it is now acceptable to put in further explanation in the body of the response. “your over quota” is a client issue that cannot be resolved until the client takes some action.
If things went badly and the “thing” is controllable by the server, return a 500 (The server encountered an unexpected condition which prevented it from fulfilling the request). Again, it is now acceptable to put in further explanation in the body of the response. “Server is undergoing maintenance” or some such is something that will clear up “later”.
Let’s not allow 200 to still require checking for error conditions. This makes the code more difficult to write for clients.
From:
opensocial-an...@googlegroups.com
[mailto:opensocial-an...@googlegroups.com] On Behalf Of Louis
Ryan
Sent: Thursday, July 31, 2008 10:06 AM
To: opensocial-an...@googlegroups.com
Subject: Re: Align OpenSocial RESTful API with PortableContacts
Now Im an unreserved +1 :)
I have question. Let's say a developer is provided with multiple
names, how would he decide which one to display?
For example, if I
have both my english name and my chinese name specified, it might make
sense for apps in the chinese locale to pick the chinese name to
display as default, so how would they identity which locale a
particular name belonged to in a list of names?
Another example might be maiden name vs married name. I might not want
my maiden name to be displayed to anyone but close friends, moreover,
I might not want it even sent over the wire to non-friends. Maiden
name is often asked as a security question for financial transactions
or health records. Imagine if my son is in my social network, and
someone is trying to commit identity theft, it might be alot easier if
they could get his mother's maiden name from his social graph.
Assuming multiple names are allowed, should there be some kind of
extra metadata that allows apps to make choices as to which name to
use for display purposes based on context?
Scott-the hope is partly that providers wouldn't have to modify the HTTP status codes to reflect application status, much as web sites often show error pages with an HTTP 200. This makes it easier for providers to be compliant, and keeps the meaning of HTTP status purer, namely was the response transmitted successfully.
My hope is that both providers and consumers could get a reasonable implementation up and running without ever having to do much with HTTP status codes--just hitting URLs and parsing JSON, which everyone can easily do.
Then as they want to present more customized errors to clients, they might start looking at HTTP, but I think if we make everyone figure out how to read/write http status codes, and make all client libraries return the status code in addition to the response body, we're just raising the barriers to casual adoption in a way that historically has caused non-trivial friction time and again, and which I feel we have the chance to avoid here.
I'm with Joseph on this one... I'd like to reframe the issue a little, maybe it will help.
1. Servers are not required to return a JSON response when they return a non-200 HTTP status code.
2. However, if a JSON response is returned, there should be a standard location in the JSON output to look for error information.
The key is #2 - if we're procesing JSON, developers need one place to look for errors, and the HTTP header doesn't seem right:
- It doesn't support application-specific error codes or additional error fields (multiple errors, warnings, error message, etc)
- The semantics of HTTP error codes don't always line up well. For example, if an app requests information that it isn't authorized to look at, you would assume that you should return a 401 UNAUTHORIZED. However, this has specific HTTP transport meaning that would be incorrect to reuse (unless you want a BASIC AUTH dialog popping up).
- As Joseph pointed out, one of the biggest benefits of the JSON API is that we return a structure that can be assigned to a variable. This is a big benefit and worth making changes to keep.
I'm +1 on the errors represented in json.Reasoning: I've worked with enough "web developers'" who "don't do error checking", let alone have the foresight to build a construction that allows for proper error handling; I've seen so many lines of code with no checking of return values on -anything- even the most vital things, that my trust that those people will be aware of curl_errno(), and take the time to wrap it's results into a custom made error structure that they can pass back is approaching 0.
The major issue with this is that we are trying to mix metaphors. The desire for the http response code of 200 in all cases with the “actual” status code in the response body is for support of user-agent/script injection/jsonp requests.
I am strongly against the idea of mixing OAuth requests with this context. So much in fact, that we may deny requests that have User-Agent values that represent a browser. We have experienced issues with consumers signing requests in the user-agent and revealing their consumer secret.
There is no reason for the status code in the response body otherwise that I can see. “Indirect Communication”/User-Agent requests, whether from form post/302/script injection all require special handling with the status code and the response body (JSONP must be wrapped in a function call after all), but most of all the security protocol.
The status code in the response body of server to server requests is a silly artifact otherwise. Establishment of a user-agent to server protocol has been danced around with this proposal as well as the OpenID+OAuth proposal and I believe it should be handled solely on it’s own.
-1 to any MUST or SHOULD on JSONP as well as the presence of the status code or any problem reporting in the response body.
+1 to any discussion on the establishment of a security context that would allow for user-agent requests. I imagine an additional parameter would be supplied on the request for the Request Token that would allow the Service Provider to provide appropriate messaging to the end user upon authorization as well as dole out a special short lived encrypted token that would not require signing of requests with any long lived shared secret.
~Paul
I’ve heard from Joe and Evan seems to concede that there are issues with user-agent/jsonp requests that should be worked out before we offer that as a use case.
I can see the need for the status code in the batched requests (although I’m not convinced for the need of batching) -- are there others? I fully support the OAuth Problem Reporting extension: http://oauth.pbwiki.com/ProblemReporting :-). I would support a MUST on this extension (we already support it on our API). It’s not finalized, so we still have a chance to enhance it.
I’m not passionate about the presence of the status code in the body, so I will rescind my -1 as long as the language is not in the context of JSONP support. Again, once we have worked out a protocol for user-agent requests, I definitely see the need for the status code in that context as well.
~Paul
There are a lot of people excited about the RESTful interface, but
there also those who think a RPC interface is a far better solution
and neither camp has been able to pull the other to their side in the
last 2 weeks.
As such currently it looks like we'll have both, a classic REST
interface for single requests, and a RPC interface too, which while it
can be construed as confusing, does cater to the desires of both sides
and does give the app developers the choice to which they prefer; Just
as long as they don't want to batch REST requests :)
So baring any -1's in the next 24 hours, i think we're ready to call
this a compromise and go for the (single request) RESTful service, and
a JSON-RPC service next to that.
-- Chris
On Aug 5, 2008, at 10:21 PM, Joseph Smarr wrote: