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 Prefer
is 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>"