Examples - ProfileNegotiation/I-D-Accept--Schema GitHub Wiki

This page collects some examples of profile negotiation. They are written in several different ways so as to make the implications of each solution better visible.

Example 1: client specifies one (preferred) profile

A client requests an XML document conforming to a specific profile. The profile is identified by urn:example:schema:e-commerce-payment.

Using Accept-Profile/Profile

Request:

GET /some-resource HTTP/1.1
Accept: application/xml
Accept-Profile: <urn:example:schema:e-commerce-payment>

Response:

HTTP/1.1 200 OK
Content-Type: application/xml
Profile: <urn:example:schema:e-commerce-payment>
Link: 	rel="self";
		type="application/xml";
		profile="<urn:example:schema:e-commerce-payment>",
		rel="alternate";
		type="application/xml";
		profile="<urn:example:schema:e-commerce-accounting>"

Using Prefer/Preference-Applied

Request:

GET /some-resource HTTP/1.1
Accept: application/xml
Prefer: profile=<urn:example:schema:e-commerce-payment>

Response:

HTTP/1.1 200 OK
Content-Type: application/xml
Vary: Prefer
Preference-Applied: profile=<urn:example:schema:e-commerce-payment>
Link: 	rel="self";
		type="application/xml";
		profile="<urn:example:schema:e-commerce-payment>",
		rel="alternate";
		type="application/xml";
		profile="<urn:example:schema:e-commerce-accounting>"

Using a custom media type

Request:

GET /some-resource HTTP/1.1
Accept: application/e-commerce-payment+xml

Response:

HTTP/1.1 200 OK
Content-Type: application/e-commerce-payment+xml
Link: 	rel="self";
		type="application/e-commerce-payment+xml",
		rel="alternate";
		type="application/e-commerce-accounting+xml"

Using Accept-Features

Request:

GET /some-resource HTTP/1.1
Accept: application/xml
Accept-Features: profile=<urn:example:schema:e-commerce-payment>
Negotiate: guess-small

Response:

HTTP/1.1 200 OK
Content-Type: application/xml
TCN: choice
Vary: negotiate
Alternates: {profile=<urn:example:schema:e-commerce-accounting>}
Link: 	rel="self";
		type="application/xml";
		profile="<urn:example:schema:e-commerce-payment>",
		rel="alternate";
		type="application/xml";
		profile="<urn:example:schema:e-commerce-accounting>"

Example 2: Client can handle several profiles and uses q-values to specify preference for one of them

A client requests an RDF/XML document conforming to one of two profiles (http://example.com/profiles/profile-1 or http://example.com/profiles/profile-2). It uses q-values to express a preference for profile-1, the server, however, decides to deliver in profile-2.

Using Accept-Profile

Request:

GET /some-resource HTTP/1.1
Accept: application/rdf+xml
Accept-Profile: <http://example.com/profiles/profile-1>; q=0.8,
                <http://example.com/profiles/profile-2>; q=0.5

Response:

HTTP/1.1 200 OK
Content-Type: application/rdf+xml
Profile: <http://example.com/profiles/profile-2>
Link:	rel="self";
		type="application/rdf+xml";
		profile="<http://example.com/profile/profile-2>",
		rel="alternate";
		type="application/rdf+xml";
		profile="<http://example.com/profile/profile-1>"

Using Prefer/Preference-Applied

Not possible, since preferences SHOULD NOT appear multiple times:

To avoid any possible ambiguity, individual preference tokens SHOULD NOT appear multiple times within a single request. If any preference is specified more than once, only the first instance is to be considered. All subsequent occurrences SHOULD be ignored without signaling an error or otherwise altering the processing of the request. This is the only case in which the ordering of preferences within a request is considered to be significant.

Using a custom media type

Request:

GET /some-resource HTTP/1.1
Accept: application/profile-1-rdf+xml; q=0.8,
        application/profile-2-rdf+xml; q=0.5

Response:

HTTP/1.1 200 OK
Content-Type: application/profile-2-rdf+xml
Link:	rel="self";
		type="application/profile-1-rdf+xml";
		rel="alternate";
		type="application/profile-2-rdf+xml";

Using Accept-Features

In this scenario the negotiation is done on the client side

Request:

GET /some-resource HTTP/1.1
Accept: application/xml
Accept-Features: profile=<urn:example:e-commerce-payment>
Negotiate: guess-small

Response:

HTTP/1.1 300 Multiple choices
Content-Type: text/html
TCN: choice
Vary: negotiate
Profile: <urn:example:schema:e-commerce-payment>
Alternates: {"some-resource-accounting" 0.9 {type application/xml} {profile <urn:example:e-commerce-accounting>}}
            {"some-resource-payment" 0.8 {type application/xml} {profile <urn:example:e-commerce-payment}}
Link: 	rel="self";
		type="application/xml";
		profile="<urn:example:schema:e-commerce-payment>",
		rel="alternate";
		type="application/xml";
		profile="<urn:example:schema:e-commerce-accounting>"

(client performs local content negotiation and decides which representation to ask for) Request:

GET /some-resource-accounting HTTP/1.1
Accept: application/xml

Response

HTTP/1.1 200 OK
Content-Type: application/xml

Example 3: Client tries to PUT data using one profile, server answers it can only process another profile

A client PUTs a turtle document conforming to the Profile http://example.com/profiles/profile-1. The server answers that it can only process documents conforming to http://example.com/profiles/profile-2.

Using Accept-Profile

Request:

PUT /some-resource HTTP/1.1
Content-Type: text/turtle
Profile: <http://example.com/profiles/profile-1>

Response:

HTTP/1.1 406 Not acceptable
Content-Type: application/xhtml+xml
Accept-Profile: <http://example.com/profiles/profile-2>
Link: rel="alternate";
		type="application/rdf+xml";
		profile="<http://example.com/profile/profile-1>"

Using Prefer/Preference-Applied

Since Preferis a request-only field, the client cannot supply any information on the profile used so the server must use heuristics to figure out if it can process the data or not. Then it can answer 406 and supply a list of supported profiles through the Link header. The relation "alternate" is probably not the right one to use, though...

Request:

PUT /some-resource HTTP/1.1
Content-Type: application/xml

Response:

HTTP/1.1 406 Not acceptable
Content-Type: application/xhtml+xml
Link: rel="alternate";
		type="application/rdf+xml";
		profile="<http://example.com/profile/profile-1>"

Using a custom media type

I don't know how the server can tell the client what media types it can handle, here I use the Link-header

Request

PUT /some-resource HTTP/1.1
Content-Type: application/profile1+xml

Response

HTTP/1.1 406 Not acceptable
Link: rel="alternate";
		type=application/profile2+xml

Using Accept-Features

RFC 2295 ยง12.2 explicitly says that transparent content negotiation is only defined for GET and HEAD, so we would need to extend that concept to use it here.

Example 4: Client requests a document that conforms to several profiles

Is this example relevant as it is currently written? XML namespaces are not profiles...

A client requests an XML document where the elements in namespace urn:example:namespaces:ns1 must conform to XML schema http://example.com/schema/schema-1 and the elements in namespace urn:example:namespaces:ns2 must conform to XML schema http://example.com/schema/schema-2. The server answers that it can supply the document as requested.

Using Accept-Profile

Request:

GET /some-resource HTTP/1.1
Accept-Profile: 	<urn:example:namespaces:ns1
				http://example.com/schema/schema-1
				urn:example:namespaces:ns2
				http://example.com/schema/schema-2>

Response:

HTTP/1.1 200 OK
Content-Type: application/xml
Profile: <urn:example:namespaces:ns1
		http://example.com/schema/schema-1
		urn:example:namespaces:ns2
		http://example.com/schema/schema-2>

Using Prefer

Request

GET /some-resource HTTP/1.1
Prefer: profile="<urn:example:namespaces:ns1
		http://example.com/schema/schema-1
		urn:example:namespaces:ns2
		http://example.com/schema/schema-2>"
Accept: application/xml

Response

HTTP/1.1 200 OK
Preference-applied: profile="<urn:example:namespaces:ns1
		http://example.com/schema/schema-1
		urn:example:namespaces:ns2
		http://example.com/schema/schema-2>"
Vary: Prefer
Content-type: application/xml
Link: 	rel="self";
		type="application/xml";
		profile="<urn:example:namespaces:ns1
		    http://example.com/schema/schema-1
		    urn:example:namespaces:ns2
		    http://example.com/schema/schema-2>",
		rel="alternate";
		type="application/xml";
		profile="<urn:example:namespaces:ns1
    		    http://example.com/schema/schema-3
		    urn:example:namespaces:ns2
		    http://example.com/schema/schema-4>"

Using a custom media type

Here we use the media type myVerySpecificMediaType+xml to say that we want XML elements from urn:example:namespaces:ns1 to conform to http://example.com/schema/schema-1 and elements from urn:example:namespaces:ns2 to conform to http://example.com/schema/schema-2.

Question: how do we nicely degrade?

Request

HEAD /some-resource HTTP/1.1
Accept: application/myVerySpecificMediaType+xml

Response

HTTP/1.1 200 OK
Content-Type: application/myVerySpecificMediaType+xml
Link: 	rel="self";
		type="application/xml";
		profile="<urn:example:namespaces:ns1
		    http://example.com/schema/schema-1
		    urn:example:namespaces:ns2
		    http://example.com/schema/schema-2>",
		rel="alternate";
		type="application/xml";
		profile="<urn:example:namespaces:ns1
    		    http://example.com/schema/schema-3
		    urn:example:namespaces:ns2
		    http://example.com/schema/schema-4>"

Using Accept-Features

Request

HEAD /some-resource HTTP/1.1
Accept: application/xml
Accept-Features: {profile=<urn:example:namespaces:ns1
		    http://example.com/schema/schema-1
		    urn:example:namespaces:ns2
		    http://example.com/schema/schema-2>}
Negotiate: guess-small

Response:

HTTP/1.1 200 OK
Content-Type: application/xml
TCN: choice
Vary: negotiate
Alternates: {{profile "<urn:example:namespaces:ns1
    		    http://example.com/schema/schema-3
		    urn:example:namespaces:ns2
		    http://example.com/schema/schema-4>"}
             {type application/xml}}
Link: 	rel="self";
		type="application/xml";
		profile="<urn:example:namespaces:ns1
    		    http://example.com/schema/schema-3
		    urn:example:namespaces:ns2
		    http://example.com/schema/schema-4>",
		rel="alternate";
		type="application/xml";
		profile="<urn:example:namespaces:ns1
    		    http://example.com/schema/schema-3
		    urn:example:namespaces:ns2
		    http://example.com/schema/schema-4>"