Abstract
Simplify everything by introducing a simple search via URI template.
Status
Open (JoeGregorio)
Rationale
Introducing Search into the APP, and mandating that the results of the search requests be Atom Feeds allows the APP to be vastly simplified. This Pace does that simplification.
The Pace drops the Introspection document, leaving that for another specification.
The Pace adds Search Resources which implement A9 OpenSearch style parametrized search URIs. The search parameters are restricted to date ranges and index ranges. The current spec has date queries but they are buried in a header and are not extensible. The use of the 'next' attribute in the current spec almost forces the server to implement indexes which I found out when implementing. Again, the search interface just takes that functionality, puts it in a common mechanism with date queries, and allows for future extensions.
Proposal
Add the following definitions to Section 3.
Entry Resource - A resource whose representation is an Atom Entry. Generic Resource - A resource whose representation is not an Atom Entry, such as an image (image/png).
The Atom Publishing Protocol operates on collections of Web resources. All collections support the same basic interactions, as do the resources within the collections. The patterns of interaction are based on the common HTTP verbs. * GET is used to retrieve a representation of a resource or perform a read-only query. * POST is used to create a new, dynamically-named resource. * PUT is used to update a known resource. * DELETE is used to remove a resource. 4.1 Editable Resources An Editable resource is a resouce that can be edited via the HTTP methods GET, PUT and DELETE. 4.1.1 Read Client Server | | | 1.) GET or HEAD to Editable Resource URI | |------------------------------------------>| | | | 2.) 200 OK | |<------------------------------------------| | | 1. The client sends a GET (or HEAD) request to the member's URI. 2. The server responds with the represenation of the resource. 4.1.2 Update Client Server | | | 1.) PUT to Editable Resource URI | |------------------------------------------>| | | | 2.) 200 OK | |<------------------------------------------| 1. The client PUTs an updated representation to the member's URI. 2. The server MAY respond with an updated representation of the member's new state. 4.1.3 Delete Client Server | | | 1.) DELETE to Editable Resource URI | |------------------------------------------>| | | | 2.) 200 Ok | |<------------------------------------------| | | 1. The client sends a DELETE request to the member's URI. 2. The server responds with successful status code. 4.2 Collections The APP groups Editable Resources with representations in Atom Entry Format into "Collections", which are analogous to the "folders" or "directories" found in many file systems. All Editable Resources that are members of a Collection have representations as Atom Entries. 4.3 Introspection To discover the capabilities of a Collection Resource, the client GET's the Collection Document from the Collection. Client Server | | | 1.) GET to Collection Resource | |--------------------------------->| | | | 2.) Collection Document | |<---------------------------------| | | 1. The client sends a GET request to the Collection Resource. 2. The server responds with an Collection Document containing a description of the capabilities of the collection. The content of this document can vary based on aspects of the client request, including, but not limited to, authentication credentials. 4.4 Listing Clients can request a listing of the collection's membership. Enumerating the Editable Resources that are members of a collection is done using one of the Search Resources listing in the Introspection Document. The Search Resource returns Atom Feed Documents with all the Entries that match the search criteria. Client Server | | | 1.) GET to Search Resource | |------------------------------->| | | | 2.) 200 OK, Atom Feed Doc | |<-------------------------------| | | 1. The client sends a GET request to the Collection's URI. 2. The server responds with an Atom Feed Document containing a full or partial listing of the collection's membership. 4.5 Authoring A client can add new Entries to a Collection by sending a request to the collection; other changes are accomplished by sending HTTP requests to the Editable Member resources. 4.5.1 Create Client Server | | | 1.) POST to Collection URI | |------------------------------->| | | | 2.) 201 Created @ Location | |<-------------------------------| | | 1. The client sends an Atom Entry Document to the server via HTTP POST. The Request URI is that of the Collection Resource. 2. The server responds with a response of "201 Created" and a "Location" header containing the URI of the newly-created resource. 4.5.2 Editing Member Resources Members of Collections are Editable Resources and are edited following the patterns in Section 4.1.
Section 4.5 "Success and Failure" Remains unchanged. (Except it is now Section 4.6)
Section 5 Collection Document The Collection Document describes the capabilites of a Collection, the types of Entries that it will accept, the types of searching it supports, etc. The Collection Document has the media-type 'application/atomcoll+xml', see Section 11 <collection xmlns="http://purl.org/atom/app"> <member-type>entry</member-type> <search-template>http://example.org/{index}</search-template> <search-template>http://example.org/d/{daterange}</search-template> </collection> 5.1 The 'app:collection' Element The "collection" element is the document element of an Collection Document, acting as a container for service data associated with one Collection. appService = element app:collection { ( appMemberType+ appSearchTemplate & anyElement* ) } The following child elements are defined by this specification: * app:collection elements MAY contain any number of app:member-type elements. * app:collection elements MAY contain any number of app:search-template elements. 5.2 The 'app:member-type' Element The 'member-type' element element contains information elements about the types of Entries that the Collection may contain. appMemberType = element app:member-type { appTypeValue } The value of appTypeValue MUST be a string that is non-empty, and matches either the "isegment-nz-nc" or the "IRI" production in [RFC3987]. Note that use of a relative reference other than a simple name is not allowed. If a name is given, implementations MUST consider the link relation type to be equivalent to the same name registered within the IANA Registry of Link Relations Section 12, and thus the IRI that would be obtained by appending the value of the rel attribute to the string "http://www.iana.org/assignments/entrytype/". The value of appTypeValue specifies constraints on the Entries that may appear in the Collection. The app:collection element may have multiple app:member-type elements. An Entry POSTed to a Collection MUST meet the constaints of at least one of the app:member-type constraints. It MAY meet more than one, but the mimimum requirement is at least one. This specification defines two initial values for app:member-type IANA registry: "entry" - The Collection is an Entry Collection as defined in Section 6. "generic" - The Collection is a Generic Collection as defined in Section 7. 5.3 The 'app:search-template' Element The 'app:search-template' element describes searching capabilites. The content of the app:search-template element is a URI Template of a Search Resource (See Section 6). Every search resource, whose URI is determined by filling in the variables in a URI Template, MUST return an Atom Feed as it's representation. The Atom Feed MUST be filled with entries that match the search critera.
Section 6 Search Resources Search resources are resources that are identified by URI Templates. They MUST return Atom Feed Documents as their representation, and unless otherwise stated the entries in the document must be ordered by their atom:updated property, with the most recently updated entries coming first in the document. Clients MUST NOT assume that the entry returned in the feed is a full representation of a member resource. If the entry is an Editable Resource then the client should perform a GET on the member resource before editing. Section 6.1 URI Templates URI Templates are a mechanisms for allowing queries using HTTP URIs. By itself a URI Template is not a valid URI. Instead there are multiple parameters embedded in the URI and distinguised by closing braces. For example: htpp://example.org/blog/edit/{index} or http://example.org/blog/{daterange} The value of each app:search-template element is a template of the URI for a Search Resource. 1. The variables in the template are enclosed in unescaped braces '{' and '}'. 1. With the exception of the variable names and their enclosing braces, the template URI MUST be properly escaped. 1. The character encoding of the template URI, and of the URI after the template is filled in, MUST be utf-8. Each URI template has one or more variables that must be substituted with the values of the named variables to construct a valid URI. 1. Substitute the brace-delimited variable, and the surrounding braces, for the desired value of that variable, ensuring that the value is also properly percent-encoded utf-8. For example, given the URI template: htpp://example.org/blog/edit/{index} and if the client wants the first 15 entries in the collection it would substitute '1-15' for {index} giving: htpp://example.org/blog/edit/1-15 Note that the template can appear at any place in the URI template: URI Template | Value of index | Expanded URI ----------------------------------------+------------------+-------------------------------------- http://example.org/{index}/search | 3-27 | http://example.org/3-27/search http://example.org/search?index={index} | 3-27 | http://example.org/search?index=3-27 Section 6.2 URI Template Variables This specification defines two variables that can be used in app:search-template values, called URI Templates. Other specifications MAY define new variables used in URI templates. An Introspection Document MUST contain at least two app:search-template elements. One of those URI Templates MUST contain only a single variable whose name is {index}. The other of the two required URI Templates MUST contain only a single variable whose name is {daterange}. There may be any number of app:search-template elements that contain URI Templates that do not match the two required by this specification. Section 6.2.1 URI Template Variable 'index' A URI Template with the variable 'index' allows querying for entries in a collection using their index when ordered by their 'updated' property. The value of the index variable should be a pair of indices separated by a dash character; either index may be optionally omitted, in which case the range is understood as stretching to infinity on that end. index-specifier = [indexnum] "-" [indexnum] The response to such a search request MUST be an Atom Feed where all the entries fall within the requested range. The request range is considered a closed set, that is, if an entry matches one end of the range exactly it MUST be included in the response. If no members fall in the requested range, the server MUST respond with an Atom Feed containing no entries. Section 6.2.2 URI Template Variable 'daterange' A URI Template with the variable 'daterange' allows querying for entries in a collection using their 'updated' property. The value of the 'daterange' variable should be a pair of iso formatted dates separated by a dash character; either index may be optionally omitted, in which case the range is understood as stretching to infinity on that end. daterange-specifier = [iso-date] "/" [iso-date] The 'iso-date' MUST conform to the "date-time" production in [RFC3339]. In addition, an uppercase "T" character MUST be used to separate date and time, and an uppercase "Z" character MUST be present in the absence of a numeric time zone offset. The response to such a search request MUST be an Atom Feed where all the entries fall within the requested range. The request range is considered a closed set, that is, if an entry matches one end of the range exactly it MUST be included in the response. If no members fall in the requested range, the server MUST respond with an Atom Feed containing no entries.
Section 7 Collection Resources This specification defines two HTTP methods for use with collection resources: GET and POST. 7.1 GET Get to a Collection Resource returns a Collection Document. 7.2 POST In addition to GET, a Collection Resource also accepts POST requests. The client POSTs a representation of the desired resource to the Collection Resource. Note that some collections only allow members of a specific media-type and a POST MAY generate a response with a status code of 415 ("Unsupported Media Type"). In the case of a successful creation, the status code MUST be 201 ("Created"). Example Request, Create a resource in a collection. In addition to GET, a Collection Resource also accepts POST requests. The client POSTs a representation of the desired resource to the Collection Resource. Note that some collections may impose constraints on the media-types that are created in a Collection. In the case of a successful creation, the status code MUST be 201 ("Created"). Example Request, Create a resource in a collection. POST /collection HTTP/1.1 Host: example.org User-Agent: Cosimo/1.0 Accept: application/atom+xml Content-Type: application/atom+xml Content-Length: nnnn <entry .... ...</entry> Here, the client is adding a new Entry to a collection. Example Response, resource created successfully. HTTP/1.1 201 Created Date: Fri, 25 Mar 2005 17:17:11 GMT Content-Length: nnnn Content-Type: application/atom+xml; charset="utf-8" Location: http://example.org/edit/first-post.atom <?xml version="1.0" encoding="UTF-8"?> <entry ... </entry> Every successful POST must return an Atom Entry in the response that describes the newly created resource. In addition a Location: header MUST be returned with the URI of the newly created resource.
Move Sections 5 of -04 here and rename as section 8.
Section 9 Generic Collection Generic Collections are Collections that do not have uniform restrictions on the representations of the member resources. 9.1 Editing Generic Resources Member resources are edited by sending HTTP requests to an individual resource's URI. Servers can determine the processing necessary to interpret a request by examining the request's HTTP method and 'Content-Type' header. Processing Client Requests GET PUT DELETE POST No Body Read x Delete x Any Body x Update x x When a query resource returns an Atom Feed enumerting the contents of a Generic Collection, all the Entries MUST have an atom:content element with a src attribute. 9.1 Title: Header The POST to a Generic Collection Resource MAY contain a Title: header that indicates the clients suggested title for the resource. The server MAY ignore the Title: header or modify the requested title to suit local conventions. Title = "Title" ":" text
Section 10 Member Resources Section 10.1 Atom Entry Extensions This specification adds three new values to the Registry of Link Relations. The value of 'collection' signifies that the IRI in the value of the href is the Collection that this Entry belongs to. The value of 'edit' signifies that the IRI in the value of the href attribute identifies the resource that is used to edit the entry. That is, it is the URI of the Entry as an Editable Resource. The value of 'srcedit' signifies that the IRI in the value of the href attribute identifies the resource that is used to edit the resource pointed to by the 'src' attribute of the atom:content element. That is, it is the URI of the atom:content@src as an Editable Resource. If the "srcedit" attribute is not given, it's value defaults to the "src" attribute of the content element. If the "srcedit" link is present, and it's value is an empty string, then there is no URI that can be treated in the way such a value would be treated. Clients SHOULD use the "srcedit" value to manipulate the resource within the context of the APP itself. Clients SHOULD prefer the "atom:content@src" value in any other context. For example, if the resource is an image, a client may replace the image data using a PUT on the "srcedit" value, and may even display a preview of the image by fetching the "srcedit" URI. But when creating a public, read-only reference to the same image resource, the client should use the "atom:content@src" value.
Section 11 Examples Section 11.1 Simple Create Here is an example of creating a simple entry. In this example the client begins with only the URI of the Collection Resource, which is: http://example.org/app/ The Entry that we wish to use to create a new resource with is: <?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom"> <title>Atom-Powered Robots Run Amok</title> <updated>2003-12-13T18:30:02Z</updated> <summary>Some text.</summary> <content type="xhtml" xml:lang="en" xml:base="http://example.org/"> <div xmlns="http://www.w3.org/1999/xhtml"> <p><i>Film at eleven.</i></p> </div> </content> </entry> As you can see this Entry has a atom:content@type of 'xhtml'. First the client retrieves the Collection Document finds out if the Collection can support this type of Entry. To retrieve the Collection Document it does a GET on the Collection Resource URI: GET /app/ HTTP/1.1 Host: example.org User-Agent: Agent/1.0 Accept: application/atomcoll+xml The Collection returns a representation the enumerates it's capabilities. HTTP/1.1 200 OK Date: Fri, 25 Mar 2005 17:15:33 GMT Last-Modified: Mon, 04 Oct 2004 18:31:45 GMT ETag: "2b3f6-a4-5b572640" Content-Type: application/atomcoll+xml; charset="utf-8" <?xml version="1.0" encoding="utf-8"?> <collection xmlns="http://purl.org/atom/app/"> <member-type>text</member-type> <member-type>html</member-type> <member-type>xhtml</member-type> <search-template>http://example.org/si/{index}</search-template> <search-template>http://example.org/bydate.cgi?{daterange}</search-template> </collection> The client finds an app:member-type element with a value of 'xhtml' so it knows that the Collection can indeed support the type of Entry it is trying to create. The client POSTs the Entry to the Collection Resource URI: POST /app/ HTTP/1.1 Host: example.org User-Agent: Cosimo/1.0 Accept: application/atom+xml Content-Type: application/atom+xml Content-Length: nnnn <?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom"> <title>Atom-Powered Robots Run Amok</title> <updated>2003-12-13T18:30:02Z</updated> <summary>Some text.</summary> <content type="xhtml" xml:lang="en" xml:base="http://example.org/"> <div xmlns="http://www.w3.org/1999/xhtml"> <p><i>Film at eleven.</i></p> </div> </content> </entry> If the resource is created successfully the response might be: HTTP/1.1 201 Created Date: Fri, 25 Mar 2005 17:17:11 GMT Content-Length: 0 Location: http://example.org/app/876 Note that the Location: header gives the URI of the newly created member resource.
Section 11.2 Resynchronization Here is an example of a client requesting all the Entries that have changed since the last time the client synchronized with the server. The last time the client resynchronized from the server was 2003-12-13T18:30:02Z. The client wishes to get all the entries that have been updated since that time. The server returns the following representation for it's Collection Resource: <?xml version="1.0" encoding="utf-8"?> <collection xmlns="http://purl.org/atom/app/"> <member-type>entry</member-type> <search-template>http://example.org/si/{index}</search-template> <search-template>http://example.org/bydate.cgi?{daterange}</search-template> </collection> We are guaranteed to find at least one 'search-template' that allows us to search by the 'updated' time. That URI in this case is: http://example.org/bydate.cgi?{daterange} We expand the URI Template with our search criteria, which is a query for all entries modified from 2003-12-13T18:30:02Z to now. The URI of that Search Resource is: http://example.org/bydate.cgi?/2003-12-13T18:30:02Z Remember that the first date in the date range is left empty if we want all entries modified until now. The response will be an Atom Feed of all the Entries that meet our criteria: HTTP/1.1 200 OK Date: Fri, 25 Mar 2005 17:15:33 GMT Last-Modified: Sun, 28 Aug 2005 18:31:45 GMT ETag: "23094-2349239-29348" Content-Type: application/atom+xml; charset="utf-8" <?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>Example Feed</title> <link href="http://example.org/"/> <updated>2005-08-28T18:30:02Z</updated> <author> <name>John Doe</name> </author> <id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id> ... <entry> <title>False Alarm on the Atom-Powered Robots Thing</title> <link href="http://example.org/2003/12/13/atom-powered-robot-retraction.html"/> <link rel="edit" href="http://example.org/app/877"/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-498593458954</id> <updated>2003-12-14T07:59:34Z</updated> <summary>Ooops</summary> <content type="xhtml" xml:lang="en" xml:base="http://example.org/"> <div xmlns="http://www.w3.org/1999/xhtml"> <p><i>What can I say, the Atom menace never materialized.</i></p> </div> </content> </entry> <entry> <title>Atom-Powered Robots Run Amok</title> <link href="http://example.org/2003/12/13/atom-powered-robots-run-amok.html"/> <link rel="edit" href="http://example.org/app/876"/> <id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id> <updated>2003-12-13T18:30:02Z</updated> <summary>Some text.</summary> <content type="xhtml" xml:lang="en" xml:base="http://example.org/"> <div xmlns="http://www.w3.org/1999/xhtml"> <p><i>Film at eleven.</i></p> </div> </content> </entry> </feed> Section 11.3 Compound Entry An example of creating a new entry with an inline image. That is, the client has an image it must publish and an entry that includes an HTML 'img' element that uses that image. In this scenario we consider a client that has URIs of two Collection Resources. The first collection handles only 'text', 'html' and 'xhtml' entries. The URI of the first collection is: http://example.net/blog/edit/ and it has a Collection representation of: <?xml version="1.0" encoding="utf-8"?> <collection xmlns="http://purl.org/atom/app/"> <member-type>entry</member-type> <search-template>http://example.net/blog/edit/{index}</search-template> <search-template>http://example.net/blog/edit/{daterange}</search-template> </collection> The second collection is a Generic Collection and is has a URI: http://example.net/binary/edit and has a Collection representation of: <?xml version="1.0" encoding="utf-8"?> <collection xmlns="http://purl.org/atom/app/"> <member-type>generic</member-type> <search-template>http://example.net/binary/edit/{index}</search-template> <search-template>http://example.net/binary/edit/{daterange}</search-template> </collection> First the client uploads the image by POSTing to the URI of the Generic Collection. POST /binary/edit/ HTTP/1.1 Host: example.net User-Agent: Thingio/1.0 Content-Type: image/png Content-Length: nnnn Title: A picture of the beach ...binary data... Which returns a 201 on success HTTP/1.1 201 Created Date: Fri, 25 Mar 2005 17:17:11 GMT Content-Length: 0 Location: http://example.net/binary/edit/b/129.png Now the last step for the client is to POST the Atom Entry that refers to the newly created image resource to the first Collection Resource. Note that the client takes the URI http://example.net/binary/readonly/129.png and uses it in the 'img' element in the Entry: POST /blog/edit/ HTTP/1.1 Host: example.net User-Agent: Thingio/1.0 Accept: application/atom+xml Content-Type: application/atom+xml Content-Length: nnnn <?xml version="1.0" encoding="utf-8"?> <entry xmlns="http://www.w3.org/2005/Atom"> <title>What I did on my summer vacation</title> <updated>2005-09-02T10:30:00Z</updated> <summary>Beach!</summary> <content type="xhtml" xml:lang="en" xml:base="http://example.org/"> <div xmlns="http://www.w3.org/1999/xhtml"> <p>We went to the beach for summer vacation. Here is a picture of the waves rolling in: <img src="http://example.net/binary/readonly/129.png" alt="A picture of the beach." /> </p> </div> </content> </entry>
Section 9 becomes Section 12 and so on.
Section 11 IANA Considerations becomes Section 14 IANA Considerations. Also remove the registration of the application/atomserv+xml media-type.
Impacts
Notes
The cardnality of member-type should be 1 or more as opposed to 0 or more.
See also PaceProtocolResponseFormat