Skip to Content.
Sympa Menu

grouper-dev - Re: [grouper-dev] real rest web services

Subject: Grouper Developers Forum

List archive

Re: [grouper-dev] real rest web services


Chronological Thread 
  • From: Scotty Logan <>
  • To: Grouper Dev <>
  • Subject: Re: [grouper-dev] real rest web services
  • Date: Fri, 15 Feb 2008 12:41:46 -0800

On Feb 15, 2008, at 10:42 AM, Chris Hyzer wrote:
Tom and I discussed real rest web services, and have a design doc which would be a layer on top of the SOAP / xml -HTTP -rpc web services.

If this is still using Axis' "RESTful" interface, then it's not going to be RESTful by any widely accepted definition.

From http://ws.apache.org/axis2/0_94/rest-ws.html:
The REST default HTTP interface is POST.

BZZZT.. The REST default HTTP interface is... HTTP. All of it.
It however acts as both a REST endpoint and SOAP endpoint. When a Message is received, if the content type is text/xml and if the SOAP Action Headers are missing, then the Message is treated as a RESTful Message. Else it is treated as a usual SOAP Message.

Right, because REST is always text/xml, because XML is the only way to represent an object.

To borrow from Henry Spencer's "10 Commandments for C Programmers" (http://www.lysator.liu.se/c/ten-commandments.html )

"Thou shalt foreswear, renounce, and abjure the vile heresy which claimeth that "All the world's [in XML]", and have no commerce with the benighted heathens who cling to this barbarous belief, that the days of thy [service] may be long even though the days of thy current [representation] be short."

For groups, as with almost any other data type, there are many others:

Content-type: text/ldif

dn: cn=foo:group,ou=Groups,dc=comanage-dev,dc=stanford,dc=edu
objectClass: groupOfNames
objectClass: eduMember
cn: foo:group
hasMember:

hasMember:

member:
,ou=People,dc=comanage-dev,dc=stanford,dc=edu
member:
,ou=People,dc=comanage-dev,dc=stanford,dc=edu

Content-type: text/lispish

("foo:group"
(""

""))

Content-type: text/ini

[Name]
foo:group

[Members]




Take a look at this outline, and let us know your thoughts, and maybe we can discuss on Wednesday.

https://wiki.internet2.edu/confluence/display/GrouperWG/Grouper+Rest+Web+Services

I don't see any real rest services in that doc.

I do see a description of a real REST interface for groups at https://wiki.cac.washington.edu/x/TpNh which was sent to this list by Bob back in early January.

Also, take a look at Paul Prescod's REST mistakes:
http://www.prescod.net/rest/mistakes/

From the wiki page:

1. URLs are resource based and not RPC based

no they're not.. you have


http://localhost:8091/grouper-ws/servicesRest/subject/12341234/getGroups

GIF image



http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup/hasMember/12341234

GIF image



http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup/addMember/12341234

GIF image



http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup/deleteMember/12341234

GIF image



http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup/deleteGroup

GIF image



http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup/saveGroup

GIF image



Those are function calls, not resource names. Resource based URLs would be

GET
http://localhost:8091/grouper-ws/servicesRest/subject/12341234/groups
GET
http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup/members/12341234

GIF image


PUT
http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup/members/12341234

GIF image

DELETE
http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup/members/12341234

GIF image


DELETE
http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup
PUT http://localhost:8091/grouper-ws/servicesRest/group/aStem:aGroup

4. Payload for the services are generally in params (similar to a form submits), which for GETs can be in the URL, and POSTs in the body of the HTTP request


Payload should be in the body, with a sensible MIME type such as application/xhtml+xml or text/ldif. Query strings for GET (and possibly DELETE, although that's potentially dangerous) should be appended to the request URI.

5. GETs and POSTs are supported only, and are interchangeable

It's hard to be RESTful when you're missing half the vocabulary. GET and POST are not interchangeable. Use GET to retrieve a representation of a resource, DELETE to remove one, PUT to create one when the client picks the name and POST when the name is determined by the server.

9. HTTP response code between 200-299 (inclusive) are a success, 400-499 (inclusive) are a problem with the request, 500-599 (inclusive) are a failure on the server. Each web service response code (e.g. IS_MEMBER) maps to a unique HTTP response code, e.g.

While you can add additional HTTP response codes, I really don't think it's a good idea. Please use existing status codes, defined in RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html. If you need to include extra information, put it in the body, or put an X- Grouper-Error: header in the response

200: SUCCESS

200 OK - for GETs and DELETEs, for PUTs or POSTs it should be 201 CREATED

220: IS_MEMBER

If this is supposed to be a response for a membership query, it's either 200 OK (the subject is a member) or 404 NOT FOUND (subject is not a member).

221: IS_NOT_MEMBER

404 NOT FOUND

222: ALREADY_MEMBER

Is this an error? If I PUT /groups/stem:name/members/newmember and they're already a member, isn't that still the desired result?

If it is an error, that's a 409 CONFLICT with a message in the body, if it's not it's a 201 CREATED.

223: WASNT_MEMBER

404 NOT FOUND, assuming it's removing a member with a DELETE

224: PARTIAL_SUCCESS_INDIRECT_MEMBER_CANT_DELETE

403 FORBIDDEN, plus some message in the reponse

420: INVALID_QUERY

400 BAD REQUEST

421: INSUFFICIENT_PRIVILEGES

403 FORBIDDEN or 405 METHOD NOT ALLOWED

422: SUBJECT_DUPLICATE

409 CONFLICT

423: SUBJECT_NOT_FOUND

424: STEM_NOT_FOUND

425: MEMBER_NOT_FOUND

426: GROUP_NOT_FOUND


404 NOT FOUND

427: GROUP_NOT_UNIQUE

409 CONFLICT

428: INDIRECT_MEMBER_CANT_DELETE

403 FORBIDDEN

520: EXCEPTION

521: PROBLEM_DELETING_MEMBERS

522: PROBLEM_WITH_ASSIGNMENT

523: PROBLEM_DELETING_GROUPS

524: SOURCE_UNAVAILABLE

525: PROBLEM_WITH_QUERY

500 INTERNAL SERVER ERROR, with a message

Also missing from the document is any mention of how to discover the groups. In a RESTful world you're not supposed to just make up the URLs on the client; there's a starting point that links to resources. E.g. something like this:

Request:

GET / HTTP/1.0
Host: group-server

Response:

200 OK
Content-type: application/xhtml+xml
Content-length: nnn

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
<head><title>Stems</title></head>
<body>
<ul class='stemlist'>
<li><a href='/groups/foo'>Foo</a></li>
<li><a href='/groups/bar'>Bar</a></li>
<li><a href='/groups/baz'>Baz</a></li>
<li><a href='/groups/boz'>Boz</a></li>
</ul>
</body>
</html>

So now you can take one of those links to get more information about a stem:

Request:

GET /groups/foo HTTP/1.0
Host: group-server

Reponse:

200 OK
Content-type: application/xhtml+xml
Content-length: nnn

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
<head><title>Foo Groups</title></head>
<body>
<ul class='grouplist'>
<li><a href='/groups/foo/BigGroup'>Big
Group</a></li>
<li><a href='/groups/bar/LittleGroup'>Little
Group</a></li>
</ul>
</body>
</html>

Then pick a group to work with:

Request:

GET /groups/foo/LittleGroup HTTP/1.0
Host: group-server

Response:

200 OK
Content-type: application/xhtml+xml
Content-length: nnn

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
<head><title>Foo:Little Group</title></head>
<body>
<h2><a rel='owners' href='/groups/foo/BigGroup/owners'>Owners</a></ h2>
<ul class='ownerlist'>
<li><a
'>Professor
X</a></li>
<li><a
'>Hoopy
Frood</a></li>
</ul>
<h2><a rel='members' href='/groups/foo/BigGroup/members'>Owners</ a></h2>
<ul class='memberlist'>
<li><a
'>Slartibartfast</a></li>
<li><a
'>Hoopy
Frood</a></li>
<li><a
'>Ford
Prefect</a></li>
...
</ul>
</body>
</html>

(The ownerlist and memberlist sections aren't really necessary).

Now you can add a new owner:

Request:

PUT
/
HTTP/1.0
Host: group-server

Response:

201 Created
Location:
http://group-server/groups/foo/BigGroup/owners/
Content-Type: text/plain
Content-Length: nnn

<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
<html xmlns="http://www.w3.org/1999/xhtml"; xml:lang="en" lang="en">
<head><title>Added Owner</title></head>
<body>
<h2>Success</h2>
<p>
Added <a rel='subject' href='/subjects/ '>Slartibartfast</a> as
an owner of <a rel='group' href='/groups/foo/ BigGroup'>foo:BigGroup</a>.
<p>
<p>
More information on group owner <a rel='owner' '>Slartibartfast</a>.
</p>
</body>
</html>

What's with the obsession with using a tool (Axis2, hammer) that is so obviously ill-suited for the task at hand (RESTful services, driving screws).

Scotty

--
Scotty Logan, IT Architect, Stanford University IT Services
http://its.stanford.edu/ http://itarch.stanford.edu/








Archive powered by MHonArc 2.6.16.

Top of Page