Per the IRC thread. He is a complete set of proposals with any backing referneces I have for them. If we agree to any of these, I would suggest we look to implement after this sprint in order to not scuttle the work of the client guys:
1:: Plurals ----------- No real reference, but is looks like most folks use /owners /customers /jedi instead of /owner /customer /jedum.
2:: Put and POST ---------------- I think we are are ok, here, but look at:
- http://jcalcote.wordpress.com/2008/10/16/put-or-post-the-rest-of-the-story/ - http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_ser... - http://code.google.com/p/django-rest-interface/wiki/BestPractices
I think we want to go with the model of PUT being idempotent, and it is used when you know "everything". If you know some thing, or need a query parameter.. it is a POST.
3:: Rest is not RPC, Resource Addresability, URL Structure --------------------------------------- This is a crap shoot of stuff, but looking at
- http://blog.linkedin.com/2009/07/08/brandon-duncan-java-one-building-consist... - http://www.slideshare.net/calamitas/restful-best-practices (first part) - http://code.google.com/p/django-rest-interface/wiki/BestPractices
It seems like we would want every resource would have a permanent uri which is:
/{resources1}/{id}
And that we could provide readable uris for important relationships
/{resources1}/{id}//{resources2}/{id}
and adopt the pattern that collections can be filterable based on query parameters:
/{resources1}?foo=bar
in part of this,
PUTTING IT ALL TOGETHER ======================= I think the following APIS which are docuemnted at:
https://fedorahosted.org/candlepin/wiki/API
would change
registerConsumer (aka POST /consumer): POST /consumers
unregisterConsumer (aka DELETE /consumer/{cosumer_uuid}): DELETE /consumers/{consumer_uuid}
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
bind: POST /entitlement/consumer/{consumer_uuid}/product/{product_id} becomes POST /consumers/{consumer_uuid}/entitlements?product={product_id}
POST /entitlement/consumer/{consumer_uuid}/token/{registration_token} becomes POST /consumers/{consumer_uuid}/entitlements?token={registration_token}
POST /entitlement/consumer/{consumer_uuid}/pool/{pool_id} becomes POST /consumers/{consumer_uuid}/entitlements?pool={pool_id}
All of these should return a new entitlement
getEntitlementPools (aka GET /entitlementpools/consumer/{consumer_uuid}/ ): GET /pools?consumer={consumer_uuid}
GET /entitlement/consumer/{dbid}/: GET /consumers/{dbid}/entitlements or GET /entitlements?consumer={dbid}
GET /owner/{dbid}/entitlement: GET /owners/{dbid}/entitlements or GET /entitlements?owner=dbid
Many other changes, but all variations on the same theme.
Thoughts, Comments, Criticisms?
Next up, which can be done later, is * HATEOAS * Paginating Collections * Versioning
-- bk
On Wed, Mar 3, 2010 at 2:25 PM, Bryan Kearney bkearney@redhat.com wrote:
PUTTING IT ALL TOGETHER
I think the following APIS which are docuemnted at:
https://fedorahosted.org/candlepin/wiki/API
would change
registerConsumer (aka POST /consumer): POST /consumers
unregisterConsumer (aka DELETE /consumer/{cosumer_uuid}): DELETE /consumers/{consumer_uuid}
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
Indeed this one does seem a little off, we're doing the POST so the client can push up the serial numbers it already has, and the server can then return just the certificates that need updating. (to cut down on bandwidth IIRC)
However I think this is where the HTTP HEAD method is meant to be used, we would expose:
/consumers/{uuid}/certificates (optional query param to list multiple ids/serials) /consumers/{uuid}/certificates/{certid/serial}
Supporting both GET/HEAD for each. HEAD would just return you the metadata (serial number, any data we need to know if it changed), whereas GET would also include the actual cert contents. Client has the option to make either method call on all certs, or a specific cert.
It would also likely mean we could clean up this CertificateStatus object which contains a Certificate.
If we're going to make the effort to clean this up proper and make it "restful" I'd like to pitch we make this change as well.
NOTE: this transfer the responsibility for determine what gets thrown out and what doesn't from the server to the client tools. I think this is a good thing, rather than the client saying "here's what's on the box, you figure out what I need, and send me instructions on what to do with each which I'll act on", the client would now say "what should I have and I'll act on that" and then acts on those results. To me this seems more logical.
bind: POST /entitlement/consumer/{consumer_uuid}/product/{product_id} becomes POST /consumers/{consumer_uuid}/entitlements?product={product_id}
POST /entitlement/consumer/{consumer_uuid}/token/{registration_token} becomes POST /consumers/{consumer_uuid}/entitlements?token={registration_token}
POST /entitlement/consumer/{consumer_uuid}/pool/{pool_id} becomes POST /consumers/{consumer_uuid}/entitlements?pool={pool_id}
Only part of this I'm wondering about, should those be query params or form params? I can't find any examples of using query params when doing a POST, I think that's usually passed in via the message body. Thoughts?
All of these should return a new entitlement
Agreed!
getEntitlementPools (aka GET /entitlementpools/consumer/{consumer_uuid}/ ): GET /pools?consumer={consumer_uuid}
GET /entitlement/consumer/{dbid}/: GET /consumers/{dbid}/entitlements or GET /entitlements?consumer={dbid}
GET /owner/{dbid}/entitlement: GET /owners/{dbid}/entitlements or GET /entitlements?owner=dbid
Many other changes, but all variations on the same theme.
Thoughts, Comments, Criticisms?
The "rest" looks good to me! :)
Cheers,
Devan
On 03/03/2010 03:13 PM, Devan Goodwin wrote:
On Wed, Mar 3, 2010 at 2:25 PM, Bryan Kearneybkearney@redhat.com wrote:
PUTTING IT ALL TOGETHER
I think the following APIS which are docuemnted at:
https://fedorahosted.org/candlepin/wiki/API
would change
registerConsumer (aka POST /consumer): POST /consumers
unregisterConsumer (aka DELETE /consumer/{cosumer_uuid}): DELETE /consumers/{consumer_uuid}
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
NOTE: this transfer the responsibility for determine what gets thrown out and what doesn't from the server to the client tools. I think this is a good thing, rather than the client saying "here's what's on the box, you figure out what I need, and send me instructions on what to do with each which I'll act on", the client would now say "what should I have and I'll act on that" and then acts on those results. To me this seems more logical.
I'm not a big fan of the sync call at all. I'd rather it just return all the currently valid certs. Not sure thats workable though.
Just returning all certs presents some problems from a ui standpoint, as it would be nice to be able to detect invalid certs before actually using them to make calls. And if entitlements are not x509's tied to content servers, then we can't invalidate them that way, and sync is probably the only way to figure out they are invalid.
bind: POST /entitlement/consumer/{consumer_uuid}/product/{product_id} becomes POST /consumers/{consumer_uuid}/entitlements?product={product_id}
POST /entitlement/consumer/{consumer_uuid}/token/{registration_token} becomes POST /consumers/{consumer_uuid}/entitlements?token={registration_token} POST /entitlement/consumer/{consumer_uuid}/pool/{pool_id} becomes POST /consumers/{consumer_uuid}/entitlements?pool={pool_id}
Only part of this I'm wondering about, should those be query params or form params? I can't find any examples of using query params when doing a POST, I think that's usually passed in via the message body. Thoughts?
Query params on the url seem okay to me. Not sure what the body would need to look like do it on the body (and/or, what can jersey do to handle that?)
That said, the /entitlement/consumer/{consumer_uuid}/pool/{pool_id} style is fine with me as well.
All of these should return a new entitlement
Agreed!
slightly redundant with the sync call, but I think it makes more sense to return entitlements here as well. Prad at least wants this.
Adrian
On 03/03/2010 03:32 PM, Adrian Likins wrote:
On 03/03/2010 03:13 PM, Devan Goodwin wrote:
On Wed, Mar 3, 2010 at 2:25 PM, Bryan Kearneybkearney@redhat.com wrote:
PUTTING IT ALL TOGETHER
I think the following APIS which are docuemnted at:
https://fedorahosted.org/candlepin/wiki/API
would change
registerConsumer (aka POST /consumer): POST /consumers
unregisterConsumer (aka DELETE /consumer/{cosumer_uuid}): DELETE /consumers/{consumer_uuid}
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
NOTE: this transfer the responsibility for determine what gets thrown out and what doesn't from the server to the client tools. I think this is a good thing, rather than the client saying "here's what's on the box, you figure out what I need, and send me instructions on what to do with each which I'll act on", the client would now say "what should I have and I'll act on that" and then acts on those results. To me this seems more logical.
I'm not a big fan of the sync call at all. I'd rather it just
return all the currently valid certs. Not sure thats workable though.
Just returning all certs presents some problems from a ui
standpoint, as it would be nice to be able to detect invalid certs before actually using them to make calls. And if entitlements are not x509's tied to content servers, then we can't invalidate them that way, and sync is probably the only way to figure out they are invalid.
How about we agree on all the stuff except this call? We could come back and and figure this one out.
bind: POST /entitlement/consumer/{consumer_uuid}/product/{product_id} becomes POST /consumers/{consumer_uuid}/entitlements?product={product_id}
POST /entitlement/consumer/{consumer_uuid}/token/{registration_token} becomes POST /consumers/{consumer_uuid}/entitlements?token={registration_token} POST /entitlement/consumer/{consumer_uuid}/pool/{pool_id} becomes POST /consumers/{consumer_uuid}/entitlements?pool={pool_id}
Only part of this I'm wondering about, should those be query params or form params? I can't find any examples of using query params when doing a POST, I think that's usually passed in via the message body. Thoughts?
Query params on the url seem okay to me. Not sure what
the body would need to look like do it on the body (and/or, what can jersey do to handle that?)
That said, the /entitlement/consumer/{consumer_uuid}/pool/{pool_id}
style is fine with me as well.
All of these should return a new entitlement
Agreed!
slightly redundant with the sync call, but I think it makes
more sense to return entitlements here as well. Prad at least wants this.
I like the idea of ../RESOURCE returning a RESOURCE
-- bk
On 03/03/2010 03:13 PM, Devan Goodwin wrote:
On Wed, Mar 3, 2010 at 2:25 PM, Bryan Kearneybkearney@redhat.com wrote:
PUTTING IT ALL TOGETHER
I think the following APIS which are docuemnted at:
https://fedorahosted.org/candlepin/wiki/API
would change
registerConsumer (aka POST /consumer): POST /consumers
unregisterConsumer (aka DELETE /consumer/{cosumer_uuid}): DELETE /consumers/{consumer_uuid}
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
Indeed this one does seem a little off, we're doing the POST so the client can push up the serial numbers it already has, and the server can then return just the certificates that need updating. (to cut down on bandwidth IIRC)
However I think this is where the HTTP HEAD method is meant to be used, we would expose:
/consumers/{uuid}/certificates (optional query param to list multiple ids/serials) /consumers/{uuid}/certificates/{certid/serial}
Supporting both GET/HEAD for each. HEAD would just return you the metadata (serial number, any data we need to know if it changed), whereas GET would also include the actual cert contents. Client has the option to make either method call on all certs, or a specific cert.
It would also likely mean we could clean up this CertificateStatus object which contains a Certificate.
If we're going to make the effort to clean this up proper and make it "restful" I'd like to pitch we make this change as well.
NOTE: this transfer the responsibility for determine what gets thrown out and what doesn't from the server to the client tools. I think this is a good thing, rather than the client saying "here's what's on the box, you figure out what I need, and send me instructions on what to do with each which I'll act on", the client would now say "what should I have and I'll act on that" and then acts on those results. To me this seems more logical.
Let me read some more about HEAD. I am all for figuring out all but this one.
bind: POST /entitlement/consumer/{consumer_uuid}/product/{product_id} becomes POST /consumers/{consumer_uuid}/entitlements?product={product_id}
POST /entitlement/consumer/{consumer_uuid}/token/{registration_token} becomes POST /consumers/{consumer_uuid}/entitlements?token={registration_token} POST /entitlement/consumer/{consumer_uuid}/pool/{pool_id} becomes POST /consumers/{consumer_uuid}/entitlements?pool={pool_id}
Only part of this I'm wondering about, should those be query params or form params? I can't find any examples of using query params when doing a POST, I think that's usually passed in via the message body. Thoughts?
So... jersey if kinda lax because I think it allows form and query to be used interchangeablye (I think). I would be fine saying "parameter" for now :)
All of these should return a new entitlement
Agreed!
getEntitlementPools (aka GET /entitlementpools/consumer/{consumer_uuid}/ ): GET /pools?consumer={consumer_uuid}
GET /entitlement/consumer/{dbid}/: GET /consumers/{dbid}/entitlements or GET /entitlements?consumer={dbid}
GET /owner/{dbid}/entitlement: GET /owners/{dbid}/entitlements or GET /entitlements?owner=dbid
Many other changes, but all variations on the same theme.
Thoughts, Comments, Criticisms?
The "rest" looks good to me! :)
Cheers,
Devan
On Wed, Mar 3, 2010 at 9:23 PM, Bryan Kearney bkearney@redhat.com wrote:
So... jersey if kinda lax because I think it allows form and query to be used interchangeablye (I think). I would be fine saying "parameter" for now :)
That's because they come across the same way IIRC. Struts used to do the same thing a form could be accessed like a query param.
jesus
On Wed, Mar 3, 2010 at 4:13 PM, Devan Goodwin dgoodwin@rm-rf.ca wrote:
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
Indeed this one does seem a little off, we're doing the POST so the client can push up the serial numbers it already has, and the server can then return just the certificates that need updating. (to cut down on bandwidth IIRC)
However I think this is where the HTTP HEAD method is meant to be used, we would expose:
/consumers/{uuid}/certificates (optional query param to list multiple ids/serials) /consumers/{uuid}/certificates/{certid/serial}
Supporting both GET/HEAD for each. HEAD would just return you the metadata (serial number, any data we need to know if it changed), whereas GET would also include the actual cert contents. Client has the option to make either method call on all certs, or a specific cert.
It would also likely mean we could clean up this CertificateStatus object which contains a Certificate.
If we're going to make the effort to clean this up proper and make it "restful" I'd like to pitch we make this change as well.
This went *almost* according to plan, turns out HTTP HEAD requests cannot return a message body, meaning you can only stuff metadata into HTTP headers. In our case we're returning a list, which to me isn't a great fit for headers and it'd probably reasonably easy to hit a length limit.
Instead I did it as a separate call, getCertificateMetadata.
Code isn't yet pushed, just adding the ability to do /consumer/{uuid}/certificates?serials=serial1,serial2,serial3 now.
Wiki updated, Prad/Jeff could you guys let me know if this looks ok or if there's anything else you guys need from it? https://fedorahosted.org/candlepin/wiki/API
During this I trimmed down ClientCertificateStatus / ClientCertificate / ClientCertificateSerialNumber / Bundle to just ClientCertificate and ClientCertificateMetadata. (former inherits from the latter)
Cheers,
Devan
Looks good.
On 03/05/2010 07:48 AM, Devan Goodwin wrote:
On Wed, Mar 3, 2010 at 4:13 PM, Devan Goodwindgoodwin@rm-rf.ca wrote:
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
Indeed this one does seem a little off, we're doing the POST so the client can push up the serial numbers it already has, and the server can then return just the certificates that need updating. (to cut down on bandwidth IIRC)
However I think this is where the HTTP HEAD method is meant to be used, we would expose:
/consumers/{uuid}/certificates (optional query param to list multiple ids/serials) /consumers/{uuid}/certificates/{certid/serial}
Supporting both GET/HEAD for each. HEAD would just return you the metadata (serial number, any data we need to know if it changed), whereas GET would also include the actual cert contents. Client has the option to make either method call on all certs, or a specific cert.
It would also likely mean we could clean up this CertificateStatus object which contains a Certificate.
If we're going to make the effort to clean this up proper and make it "restful" I'd like to pitch we make this change as well.
This went *almost* according to plan, turns out HTTP HEAD requests cannot return a message body, meaning you can only stuff metadata into HTTP headers. In our case we're returning a list, which to me isn't a great fit for headers and it'd probably reasonably easy to hit a length limit.
Instead I did it as a separate call, getCertificateMetadata.
Code isn't yet pushed, just adding the ability to do /consumer/{uuid}/certificates?serials=serial1,serial2,serial3 now.
Please update the wiki to reflect the list of serial# param. Or, am I missing something?
Wiki updated, Prad/Jeff could you guys let me know if this looks ok or if there's anything else you guys need from it? https://fedorahosted.org/candlepin/wiki/API
During this I trimmed down ClientCertificateStatus / ClientCertificate / ClientCertificateSerialNumber / Bundle to just ClientCertificate and ClientCertificateMetadata. (former inherits from the latter)
Cheers,
Devan
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 03/05/2010 08:48 AM, Devan Goodwin wrote:
On Wed, Mar 3, 2010 at 4:13 PM, Devan Goodwin dgoodwin@rm-rf.ca wrote:
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): � � � �POST /consumers/{consumer_uuid}/certificates � � � �This is a bit off standard, but I think we are ok
Indeed this one does seem a little off, we're doing the POST so the client can push up the serial numbers it already has, and the server can then return just the certificates that need updating. (to cut down on bandwidth IIRC)
However I think this is where the HTTP HEAD method is meant to be used, we would expose:
/consumers/{uuid}/certificates (optional query param to list multiple ids/serials) /consumers/{uuid}/certificates/{certid/serial}
Supporting both GET/HEAD for each. HEAD would just return you the metadata (serial number, any data we need to know if it changed), whereas GET would also include the actual cert contents. Client has the option to make either method call on all certs, or a specific cert.
It would also likely mean we could clean up this CertificateStatus object which contains a Certificate.
If we're going to make the effort to clean this up proper and make it "restful" I'd like to pitch we make this change as well.
This went *almost* according to plan, turns out HTTP HEAD requests cannot return a message body, meaning you can only stuff metadata into HTTP headers. In our case we're returning a list, which to me isn't a great fit for headers and it'd probably reasonably easy to hit a length limit.
Instead I did it as a separate call, getCertificateMetadata.
Code isn't yet pushed, just adding the ability to do /consumer/{uuid}/certificates?serials=serial1,serial2,serial3 now.
Wiki updated, Prad/Jeff could you guys let me know if this looks ok or if there's anything else you guys need from it? https://fedorahosted.org/candlepin/wiki/API
During this I trimmed down ClientCertificateStatus / ClientCertificate / ClientCertificateSerialNumber / Bundle to just ClientCertificate and ClientCertificateMetadata. (former inherits from the latter)
Would it be better to have a serial number resource which the client makes a GET request against (no params except maybe consumer_uuid) which would return ALL serial numbers, then let the client do the diff making a request for any missing certificates?
GET /consumer/{consumer_uuid}/serialnumbers/
Response would be a list of serial numbers, client diffs this list with its current list. Any diff, would be a call to
GET /consumer/{consumer_uuid}/certificates?serials=missingserial1,ms2,m4
jesus
- -- jesus m. rodriguez | jesusr@redhat.com principal software engineer | irc: zeus red hat systems management | 919.754.4413 (w) rhce # 805008586930012 | 919.623.0080 (c) +---------------------------------------------+ | "Those who cannot remember the past | | are condemned to repeat it." | | -- George Santayana | +---------------------------------------------+
On 03/05/2010 09:50 AM, Jesus M. Rodriguez wrote:
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 03/05/2010 08:48 AM, Devan Goodwin wrote:
On Wed, Mar 3, 2010 at 4:13 PM, Devan Goodwindgoodwin@rm-rf.ca wrote:
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): � � � �POST /consumers/{consumer_uuid}/certificates � � � �This is a bit off standard, but I think we are ok
Indeed this one does seem a little off, we're doing the POST so the client can push up the serial numbers it already has, and the server can then return just the certificates that need updating. (to cut down on bandwidth IIRC)
However I think this is where the HTTP HEAD method is meant to be used, we would expose:
/consumers/{uuid}/certificates (optional query param to list multiple ids/serials) /consumers/{uuid}/certificates/{certid/serial}
Supporting both GET/HEAD for each. HEAD would just return you the metadata (serial number, any data we need to know if it changed), whereas GET would also include the actual cert contents. Client has the option to make either method call on all certs, or a specific cert.
It would also likely mean we could clean up this CertificateStatus object which contains a Certificate.
If we're going to make the effort to clean this up proper and make it "restful" I'd like to pitch we make this change as well.
This went *almost* according to plan, turns out HTTP HEAD requests cannot return a message body, meaning you can only stuff metadata into HTTP headers. In our case we're returning a list, which to me isn't a great fit for headers and it'd probably reasonably easy to hit a length limit.
Instead I did it as a separate call, getCertificateMetadata.
Code isn't yet pushed, just adding the ability to do /consumer/{uuid}/certificates?serials=serial1,serial2,serial3 now.
Wiki updated, Prad/Jeff could you guys let me know if this looks ok or if there's anything else you guys need from it? https://fedorahosted.org/candlepin/wiki/API
During this I trimmed down ClientCertificateStatus / ClientCertificate / ClientCertificateSerialNumber / Bundle to just ClientCertificate and ClientCertificateMetadata. (former inherits from the latter)
Would it be better to have a serial number resource which the client makes a GET request against (no params except maybe consumer_uuid) which would return ALL serial numbers, then let the client do the diff making a request for any missing certificates?
GET /consumer/{consumer_uuid}/serialnumbers/
Or.. look at slide 10 of this:
http://blog.linkedin.com/2009/07/08/brandon-duncan-java-one-building-consist...
-- bk
On Fri, Mar 5, 2010 at 10:50 AM, Jesus M. Rodriguez jesusr@redhat.com wrote:
Would it be better to have a serial number resource which the client makes a GET request against (no params except maybe consumer_uuid) which would return ALL serial numbers, then let the client do the diff making a request for any missing certificates?
GET /consumer/{consumer_uuid}/serialnumbers/
Jeff noticed this too, it's a little weird to have a metadata call returning nothing but serial numbers. I was thinking that at some point we *might* discover a need for some other little piece of metadata, maybe a status field or a created/modified date, which in the metadata case we could add in without busting anything querying for serial number now.
However it might be safe to assume the list of serial numbers is all the info the client tools will need, in which case I can switch that to a serialnumbers call easily. Shall we?
----- "Devan Goodwin" dgoodwin@rm-rf.ca wrote:
On Fri, Mar 5, 2010 at 10:50 AM, Jesus M. Rodriguez jesusr@redhat.com wrote:
Would it be better to have a serial number resource which the
client
makes a GET request against (no params except maybe consumer_uuid) which would return ALL serial numbers, then let the client do the diff making a request for any missing certificates?
GET /consumer/{consumer_uuid}/serialnumbers/
Jeff noticed this too, it's a little weird to have a metadata call returning nothing but serial numbers. I was thinking that at some point we *might* discover a need for some other little piece of metadata, maybe a status field or a created/modified date, which in the metadata case we could add in without busting anything querying for serial number now.
However it might be safe to assume the list of serial numbers is all the info the client tools will need, in which case I can switch that to a serialnumbers call easily. Shall we?
+1
-- Devan Goodwin dgoodwin@rm-rf.ca http://rm-rf.ca _______________________________________________ candlepin mailing list candlepin@lists.fedorahosted.org https://fedorahosted.org/mailman/listinfo/candlepin
On Wed, Mar 3, 2010 at 1:25 PM, Bryan Kearney bkearney@redhat.com wrote:
Per the IRC thread. He is a complete set of proposals with any backing referneces I have for them. If we agree to any of these, I would suggest we look to implement after this sprint in order to not scuttle the work of the client guys:
1:: Plurals
No real reference, but is looks like most folks use /owners /customers /jedi instead of /owner /customer /jedum.
Not sure how the framework handles this without moving them to a new Resource class. Today we have an @Path("/owner") at the top of the OwnerResource, maybe we remove that and put @Path on individual methods otherwise, we're looking at OwnersResource, CustomersResource, JediResource (nothing to see in this one).
2:: Put and POST
I think we are are ok, here, but look at:
http://jcalcote.wordpress.com/2008/10/16/put-or-post-the-rest-of-the-story/
http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_ser...
I think we want to go with the model of PUT being idempotent, and it is used when you know "everything". If you know some thing, or need a query parameter.. it is a POST.
I'm good with that.
3:: Rest is not RPC, Resource Addresability, URL Structure
This is a crap shoot of stuff, but looking at
http://blog.linkedin.com/2009/07/08/brandon-duncan-java-one-building-consist...
- http://www.slideshare.net/calamitas/restful-best-practices (first part)
- http://code.google.com/p/django-rest-interface/wiki/BestPractices
It seems like we would want every resource would have a permanent uri which is:
/{resources1}/{id}
And that we could provide readable uris for important relationships
/{resources1}/{id}//{resources2}/{id}
and adopt the pattern that collections can be filterable based on query parameters:
/{resources1}?foo=bar
in part of this,
+1 I'm good with this as well.
PUTTING IT ALL TOGETHER
I think the following APIS which are docuemnted at:
https://fedorahosted.org/candlepin/wiki/API
would change
registerConsumer (aka POST /consumer): POST /consumers
unregisterConsumer (aka DELETE /consumer/{cosumer_uuid}): DELETE /consumers/{consumer_uuid}
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
bind: POST /entitlement/consumer/{consumer_uuid}/product/{product_id} becomes POST /consumers/{consumer_uuid}/entitlements?product={product_id}
POST /entitlement/consumer/{consumer_uuid}/token/{registration_token} becomes POST /consumers/{consumer_uuid}/entitlements?token={registration_token}
POST /entitlement/consumer/{consumer_uuid}/pool/{pool_id} becomes POST /consumers/{consumer_uuid}/entitlements?pool={pool_id}
All of these should return a new entitlement
getEntitlementPools (aka GET /entitlementpools/consumer/{consumer_uuid}/ ): GET /pools?consumer={consumer_uuid}
GET /entitlement/consumer/{dbid}/: GET /consumers/{dbid}/entitlements or GET /entitlements?consumer={dbid}
GET /owner/{dbid}/entitlement: GET /owners/{dbid}/entitlements or GET /entitlements?owner=dbid
Many other changes, but all variations on the same theme.
Thoughts, Comments, Criticisms?
Next up, which can be done later, is
- HATEOAS
- Paginating Collections
- Versioning
Definitely will need versioning, because this is something we had a problem with in Spacewalk making it difficult to change APIs trying to keep them moving forward and backwards compatible at the same time.
jesus
On Wed, Mar 3, 2010 at 6:05 PM, Jesus M. Rodriguez jmrodri@gmail.com wrote:
1:: Plurals
No real reference, but is looks like most folks use /owners /customers /jedi instead of /owner /customer /jedum.
Not sure how the framework handles this without moving them to a new Resource class. Today we have an @Path("/owner") at the top of the OwnerResource, maybe we remove that and put @Path on individual methods otherwise, we're looking at OwnersResource, CustomersResource, JediResource (nothing to see in this one).
Can't we just change the @Path to point to "/owners" across the board? I was reading this as changing to plurals for all resources all the time but I may have gotten a wire crossed there.
On 03/03/2010 06:57 PM, Devan Goodwin wrote:
On Wed, Mar 3, 2010 at 6:05 PM, Jesus M. Rodriguezjmrodri@gmail.com wrote:
1:: Plurals
No real reference, but is looks like most folks use /owners /customers /jedi instead of /owner /customer /jedum.
Not sure how the framework handles this without moving them to a new Resource class. Today we have an @Path("/owner") at the top of the OwnerResource, maybe we remove that and put @Path on individual methods otherwise, we're looking at OwnersResource, CustomersResource, JediResource (nothing to see in this one).
Can't we just change the @Path to point to "/owners" across the board? I was reading this as changing to plurals for all resources all the time but I may have gotten a wire crossed there.
Yes, that is what I was thinking... should be just mucking with the @Path annotations.
-- bk
On Wed, Mar 3, 2010 at 6:57 PM, Devan Goodwin dgoodwin@rm-rf.ca wrote:
On Wed, Mar 3, 2010 at 6:05 PM, Jesus M. Rodriguez jmrodri@gmail.com wrote:
1:: Plurals
No real reference, but is looks like most folks use /owners /customers /jedi instead of /owner /customer /jedum.
Not sure how the framework handles this without moving them to a new Resource class. Today we have an @Path("/owner") at the top of the OwnerResource, maybe we remove that and put @Path on individual methods otherwise, we're looking at OwnersResource, CustomersResource, JediResource (nothing to see in this one).
Can't we just change the @Path to point to "/owners" across the board? I was reading this as changing to plurals for all resources all the time but I may have gotten a wire crossed there.
Nope, I misread the original, I read it as "/owners /customers /jedi *AND* /owner /customer /jedum"
because that's what I'm used to seeing /owner for a single and plurals for collections. But if we're going with plurals across the board then the @Path isn't a problem at all.
jesus
On 03/03/2010 05:05 PM, Jesus M. Rodriguez wrote:
On Wed, Mar 3, 2010 at 1:25 PM, Bryan Kearneybkearney@redhat.com wrote:
Per the IRC thread. He is a complete set of proposals with any backing referneces I have for them. If we agree to any of these, I would suggest we look to implement after this sprint in order to not scuttle the work of the client guys:
1:: Plurals
No real reference, but is looks like most folks use /owners /customers /jedi instead of /owner /customer /jedum.
Not sure how the framework handles this without moving them to a new Resource class. Today we have an @Path("/owner") at the top of the OwnerResource, maybe we remove that and put @Path on individual methods otherwise, we're looking at OwnersResource, CustomersResource, JediResource (nothing to see in this one).
2:: Put and POST
I think we are are ok, here, but look at:
http://jcalcote.wordpress.com/2008/10/16/put-or-post-the-rest-of-the-story/
http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_ser...
I think we want to go with the model of PUT being idempotent, and it is used when you know "everything". If you know some thing, or need a query parameter.. it is a POST.
I'm good with that.
3:: Rest is not RPC, Resource Addresability, URL Structure
This is a crap shoot of stuff, but looking at
http://blog.linkedin.com/2009/07/08/brandon-duncan-java-one-building-consist...
- http://www.slideshare.net/calamitas/restful-best-practices (first part)
- http://code.google.com/p/django-rest-interface/wiki/BestPractices
It seems like we would want every resource would have a permanent uri which is:
/{resources1}/{id}
And that we could provide readable uris for important relationships
/{resources1}/{id}//{resources2}/{id}
and adopt the pattern that collections can be filterable based on query parameters:
/{resources1}?foo=bar
in part of this,
+1 I'm good with this as well.
PUTTING IT ALL TOGETHER
I think the following APIS which are docuemnted at:
https://fedorahosted.org/candlepin/wiki/API
would change
registerConsumer (aka POST /consumer): POST /consumers
unregisterConsumer (aka DELETE /consumer/{cosumer_uuid}): DELETE /consumers/{consumer_uuid}
syncCertificates (aka POST /consumer/{consumer_uuid}/certificates): POST /consumers/{consumer_uuid}/certificates This is a bit off standard, but I think we are ok
bind: POST /entitlement/consumer/{consumer_uuid}/product/{product_id} becomes POST /consumers/{consumer_uuid}/entitlements?product={product_id}
POST /entitlement/consumer/{consumer_uuid}/token/{registration_token} becomes POST /consumers/{consumer_uuid}/entitlements?token={registration_token} POST /entitlement/consumer/{consumer_uuid}/pool/{pool_id} becomes POST /consumers/{consumer_uuid}/entitlements?pool={pool_id} All of these should return a new entitlement
getEntitlementPools (aka GET /entitlementpools/consumer/{consumer_uuid}/ ): GET /pools?consumer={consumer_uuid}
GET /entitlement/consumer/{dbid}/: GET /consumers/{dbid}/entitlements or GET /entitlements?consumer={dbid}
GET /owner/{dbid}/entitlement: GET /owners/{dbid}/entitlements or GET /entitlements?owner=dbid
Many other changes, but all variations on the same theme.
Thoughts, Comments, Criticisms?
Next up, which can be done later, is
- HATEOAS
- Paginating Collections
- Versioning
Definitely will need versioning, because this is something we had a problem with in Spacewalk making it difficult to change APIs trying to keep them moving forward and backwards compatible at the same time.
Where would you suggest it? Would you put it into /v1/RESOURCE.... or /RESOURCE/v1/....
-- bk
On Fri, Mar 5, 2010 at 2:13 PM, Dmitri Dolguikh ddolguik@redhat.com wrote:
Where would you suggest it? Would you put it into /v1/RESOURCE.... or /RESOURCE/v1/....
-- bk
my vote is for /v1/RESOURCE scheme - the most common thing comes first?
I'm ok with either as long as it does not have v in it :) i.e. /1.2.1/RESOURCE vs /v1.2.1/RESOURCE :)
jesus
candlepin@lists.fedorahosted.org