rave-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Erin Noe-Payne <erin.noe.pa...@gmail.com>
Subject Re: [Proposal] REST API interface
Date Tue, 16 Jul 2013 17:32:09 GMT
Any further discussion here? I would like to start implementing more
of the REST APIs, as it is foundational for the entire angular
architecture.

My understanding from Matt is that the current apis in trunk are
mostly proof of concept - they are not tested and much of the
functionality is just stubbed. Are any of the rest api implementations
in the code base a good working example? Is there other documentation
we can reference?

On Thu, Jul 11, 2013 at 5:48 PM, Erin Noe-Payne
<erin.noe.payne@gmail.com> wrote:
> On Thu, Jul 11, 2013 at 5:02 PM, Matt Franklin <m.ben.franklin@gmail.com> wrote:
>> +1 for every one of Chris' +1s, unless otherwise noted.
>>
>> On Thu, Jul 11, 2013 at 3:47 PM, Chris Geer <chris@cxtsoftware.com> wrote:
>>
>>> Oh boy!! :)
>>>
>>> Comments inline
>>>
>>>
>>> On Thu, Jul 11, 2013 at 1:20 PM, Erin Noe-Payne <erin.noe.payne@gmail.com
>>> >wrote:
>>>
>>> > Hey All,
>>> >
>>> > As we are starting to look at the rest apis in more detail, I would
>>> > like to discuss and agree upon a consistent interface for our apis.
>>> > We currently have several developers interested in contributing to the
>>> > apis and the angular branch, and I would like to solidify the
>>> > interface, methods, response format, etc so that we can be on the same
>>> > page going forward. If we can agree on an api virtualization layer
>>> > then we should be able to build against it on the server and on the
>>> > angular application in parallel.
>>> >
>>> > I'll start with a proposal and look for feedback to iterate from there.
>>> >
>>> > 1. API root url
>>> >
>>> > "/api". Drop support for rpc api, move from /api/rest to just /api.
>>> >
>>>
>>> +1 - the only downside of this is that it prohibits implementing over time
>>> and requires a rip/replace approach of the whole system
>
> Well the development in trunk can continue to happen on /rest. Angular
> (aka the consuming client for most of these apis) is already happening
> in a branch, so those changes can be treated as a rip / replace
> easily.
>
>>>
>>> >
>>> > 2. Media Types
>>> >
>>> > Initially support only application/json. We can revisit
>>> > application/xml as a nice-to-have.
>>> >
>>>
>>> +1
>>>
>>> >
>>> > 3. HTTP Methods
>>> >
>>> > GET, PUT, POST, DELETE
>>> >
>>>
>>> +1 (We also need to decide if PUT can handle partial updates)
>>>
>>
>> I say not.  That is what PATCH is for, once everything supports it:
>> http://tools.ietf.org/html/rfc5789
>
> My understanding is that PUT should always be a full object replace. A
> quick search returns the suggestion to use PATCH, or to use POST to a
> subresource with a 303 response.
>
>>
>>>
>>> >
>>> > 4. Status Codes
>>> >
>>> > 200, 201, 400, 401, 403, 404, 500
>>> >
>>>
>>> +1
>>>
>>> >
>>> > 5. URL formats
>>> >
>>> > Use plural nouns (pages, people, widgets). Do not nest associations
>>> > beyond one level deep. For example:
>>> > /pages/1/regions (ok)
>>> > /pages/1/regions/2/regionwidgets (not ok)
>>> > /regions/2/regionwidgets (ok)
>>> >
>>>
>>> I'm not a fan of this requirement. Your example is the exact reason I'm not
>>> a fan actually. In all reality, regions don't mean anything outside a page,
>>> and region widgets don't mean anything outside of a region. Yes, they have
>>> IDs, but in reality, those IDs should be subordinate to the parent (so
>>> there should be nothing wrong with having Page 1 with regions [1,2] and
>>> Page 2 with regions [1,2]). I understand that's not how the DB works today
>>> but it's what makes the most logical sense.
>>>
>>
>> I agree with Chris. We should not limit to a single level. That is counter
>> to a few REST web service principles.
>>
>
> Fair enough. In this case I guess I would just be looking for
> consistency - will associations be infinitely nest-able. If not, what
> is the rule to determine where we support more or less deeply nested
> associations.
>
>>
>>> >
>>> > 6. Response formats
>>> >
>>> > 6a. Wrap all responses in an object. All valid (200) responses should
>>> > be wrapped in an object that includes a "meta" object for metadata,
>>> > and a "data" object for the response body. This allows us to capture
>>> > or extend metadata associated with a response as needed. Any metadata
>>> > properties should be standardized.
>>> >
>>> > Example:
>>> >
>>> > GET /people
>>> > {
>>> >  meta: {count: 253, limit: 10, offset: 0, ...}
>>> >  data: [ {id: 1, name: 'canonical', ...}, ... ]
>>> > }
>>> >
>>> > GET /people/1
>>> > {
>>> >  meta: { ... }
>>> >  data: {id:1, name: 'canonical', ...}
>>> > }
>>> >
>>>
>>> This really complicates a couple things, first, it means the GET != PUT
>>> since the GET will include the meta data. Can we achieve this same result
>>> with HTTP Headers?
>>>
>
> We could possibly achieve the same with HTTP headers. I prefer the
> object approach for clarity, since custom http headers are less
> accessible or discoverable than object structure. I get your point,
> but I see the wrapped object approach used commonly in major apis. If
> it's clearly documented and used consistently across the entire api I
> don't really see an issue.
>
>>> >
>>> > 6b. Error objects. In the case of an error, the correct error code
>>> > should be returned. In addition, an error object should be returned
>>> > with a standardized format. Ideally including a verbose,
>>> > human-readable error message for developers, and an internationalized
>>> > readable error message for display to end users.
>>> >
>>> > GET /people/25
>>> > 401
>>> > {
>>> >  developerMessage: 'Unauthorized. Access to this resource requires
>>> > authentication',
>>> >  userMessage: 'Please login',
>>> >  stackTrace: ...
>>> > }
>>> >
>>>
>>> +1
>>>
>>> >
>>> > 6c. Partial responses. By default all responses, whether a list or
>>> > individual resource, should return a full representation of the
>>> > resources (not including security constraints).  All endpoints should
>>> > support the query string parameter "fields", which accepts a comma
>>> > delimited list of fields to build a partial response.
>>> >
>>>
>>> Hmmm.....what's funny (except for the wasted work) is this is how I
>>> originally  built the people resource. I changed it because the "fields"
>>> approach gets almost impossible to manage with nested elements (at least in
>>> Java - rewrite in Ruby anyone??). I'm open to suggestions though. I guess
>>> we could also make a rule that the data objects shouldn't have nested
>>> elements but that is a tough rule.
>>>
>>
>> I think the fields approach makes sense long-term; but, it is not critical.
>>
>>
>
> I don't really know what the implementation looks like. If you allow
> field filtering only on properties and deliver only properties (i.e.
> no nested objects / associations) then I would assume it is pretty
> straightforward.
>>>
>>> >
>>> > GET /people/1
>>> > {
>>> >  meta: { ... },
>>> >  data: { id: 1, name: 'canonical', email: 'canonical@gmail.com', ... }
>>> > }
>>> >
>>> > GET /people/1?fields=id,name
>>> > {
>>> >  meta: { ... },
>>> >  data: { id: 1, name: 'canonical' }
>>> > }
>>> >
>>> > 6d. Pagination. All requests that return a list should be paginated.
>>> > The query string parameters "limit" and "offset" should be used for
>>> > pagination. On any request in which either parameter is not set, they
>>> > should default to 10 and 0 respectively.
>>> >
>>>
>>> +1
>>>
>>> >
>>> > 6e. Use camelCase for properties.
>>> >
>>>
>>> +1
>>>
>>> >
>>> > 7. Endpoints.
>>> >
>>> > 7a. Standard endpoints: there should be standard CRUD endpoints to
>>> > support each rave resource. In other words, any operation possible in
>>> > rave should be possible through a rest api action.
>>> >
>>>
>>> +1
>>>
>>> >
>>> > 7b. Special endpoints. In the case of certain client needs, we can
>>> > implement a small number of special endpoints to fulfill a specific
>>> > role. The primary case in point is retrieving a page for render, which
>>> > returns a page, its regions, its regionWidgets, and their render data.
>>> >
>>>
>>> +1
>>>
>>> >
>>> >
>>> >
>>> > Ok, I think that's it. This is meant as a proposal only - we are
>>> > looking for feedback to go forward. Thoughts?
>>> >
>>>

Mime
View raw message