@@ -345,6 +345,305 @@ Q: Why this document?
345345 This has some security implications too
346346 (eg. wrt on identifying parsers or treat downloads)
347347
348+ # Examples of content negotiation
349+ {: numbered="false" removeinrfc="true"}
350+
351+ This section explores the possibilities for User Agents
352+ to retrieve information about API specifications
353+ using their preferred version of OpenAPI.
354+
355+ # # Scenarios
356+ {: numbered="false" removeinrfc="true"}
357+
358+ An API catalog exposes API specifications using OAS 3.0,
359+ and it wants to provide migration/upgrade capabilities
360+ to future versions of OAS and JSON Schema.
361+ For simplicity, we use only YAML serialization.
362+
363+ Resource : https://example.org/openapi.yaml
364+ : is an OpenAPI Specification document
365+ that references the Foo schema located at /foo.yaml.
366+
367+ ~~~ http
368+ HTTP/1.1 200 OK
369+ Content-Location : openapi.yaml
370+ Content-Type : application/openapi+yaml; version=3.0
371+
372+ openapi : 3.0.0
373+ …
374+ components :
375+ schemas :
376+ Foo :
377+ " $ref " : " /foo.yaml"
378+ ~~~
379+
380+ ~~~ http
381+ HTTP/1.1 200 OK
382+ Content-Location : openapi.yaml
383+ Content-Type : application/openapi+yaml; version=3.2
384+
385+ openapi : 3.2.0
386+ " $self " : https://example.com/openapi.yaml
387+ …
388+ components :
389+ schemas :
390+ Foo :
391+ " $ref " : /foo.yaml
392+ ~~~
393+
394+ Resource : https://example.org/foo.yaml
395+ : is the schema definition for Foo,
396+ represented in two different ways
397+ depending on the OpenAPI version requested.
398+
399+ ~~~ http
400+ HTTP/1.1 200 OK
401+ Content-Location : foo.yaml
402+ Content-Type : application/whatever+yaml
403+
404+ type : string
405+ enum : [ it, en]
406+ ~~~
407+
408+ Since OAS 3.2 supports JSON Schema,
409+ the same syntax can be described
410+ adding a `title` to each enum value.
411+
412+ ~~~ http
413+ HTTP/1.1 200 OK
414+ Content-Location : foo.yaml
415+ Content-Type : application/whatever+yaml
416+
417+ " $schema " : " https://json-schema.org/draft/2020-12/schema"
418+ " $id " : " https://example.com/foo.yaml"
419+ oneOf :
420+ - const : it
421+ title : Italian
422+ - const : en
423+ title : English
424+ ~~~
425+
426+ # ## Scenario 1
427+ {: numbered="false" removeinrfc="true"}
428+
429+ The User Agent only supports OAS3.0
430+ and refuses other formats,
431+ including the more generic ones
432+ (see {{Section 12.4.3 of HTTP}}.
433+
434+ ~~~ http
435+ GET /openapi.yaml HTTP/1.1
436+ Host : example.com
437+ Accept : \
438+ application/openapi+yaml; version=3.0,
439+ */*; q=0
440+ ~~~
441+
442+ The server responds with the desired resource.
443+
444+ ~~~ http
445+ HTTP/1.1 200 OK
446+ Content-Type : application/openapi+yaml; version=3.0
447+
448+ openapi : 3.0.0
449+ …
450+ components :
451+ schemas :
452+ Foo :
453+ " $ref " : /foo.yaml
454+ ~~~
455+
456+ The User Agent processes the content
457+ and to resolve the `$ref`, requests the /foo.yaml.
458+
459+ It needs to retrieve a content compatible with
460+ the entry document.
461+ While the User Agent expects a JSON or YAML serialized content,
462+ compatible with OAS3.0,
463+ it cannot know the actual format that the server will return.
464+
465+ ~~~ http
466+ GET /foo.yaml HTTP/1.1
467+ Host : example.com
468+ Accept : application/openapi+yaml; version=3.0; q=1, application/yaml; q=0.5
469+ ~~~
470+
471+ The server responds with a YAML serialized content
472+ that is compatible with OAS3.0.
473+ Since the content only contains a Schema Object,
474+ that is not associated with any media type,
475+ the server uses the `application/yaml` media type.
476+
477+ ~~~ http
478+ HTTP/1.1 200 OK
479+ Content-Type : application/yaml
480+
481+ type : string
482+ enum : [it, en]
483+ ~~~
484+
485+ # ## Scenario 2
486+ {: numbered="false" removeinrfc="true"}
487+
488+ The User Agent prefers OAS3.2;
489+ moreover uses the `q` parameter
490+ to decline OAS3.0 documents.
491+ If it weren't so, the server
492+ could have responded with the older version
493+ if the OAS3.2 document were not available.
494+
495+ ~~~ http
496+ GET /openapi.yaml HTTP/1.1
497+ Host : example.com
498+ Accept : application/openapi+yaml; version=3.2, application/openapi+yaml; version=3.0;q=0
499+ ~~~
500+
501+ The server responds with the OAS3.2 document.
502+
503+ ~~~ http
504+ HTTP/1.1 200 OK
505+ Content-Type : application/openapi+yaml; version=3.2
506+
507+ openapi : 3.0.0
508+ …
509+ components :
510+ schemas :
511+ Foo :
512+ " $ref " : /foo.yaml
513+ ~~~
514+
515+ The User Agent then requests the /foo.yaml,
516+ but it wants to retrieve a content with the most recent OAS version.
517+
518+ ~~~ http
519+ GET /foo.yaml HTTP/1.1
520+ Host : example.com
521+ Accept : application/openapi+yaml; version=3.2
522+ ~~~
523+
524+ The server processes the Accept header,
525+ and it realizes that the User Agent
526+ prefers an OAS3.2 compatible content.
527+ It then choses the JSON Schema representation
528+ and responds accordingly.
529+
530+ Since JSON Schema has no associated media type,
531+ the server uses the `application/yaml` media type.
532+
533+ ~~~ http
534+ HTTP/1.1 200 OK
535+ Content-Type : application/yaml
536+
537+ " $schema " : " https://json-schema.org/draft/2020-12/schema"
538+ " $id " : " https://example.com/foo.yaml"
539+ oneOf :
540+ - const : it
541+ title : Italian
542+ - const : en
543+ title : English
544+ ~~~
545+
546+ # ## Scenario 3
547+ {: numbered="false" removeinrfc="true"}
548+
549+ In this scenario :
550+
551+ 1. the User Agent express preference
552+ for referenced resources compatible with OAS3.2.
553+ 1. The server enforces a strict content negotiation,
554+ and responds with a 406 Not Acceptable;
555+ 1. the User Agent will have to retry
556+ using one of the acceptable media types.
557+
558+ The User Agent prefers OAS3.2;
559+ moreover uses the `q` parameter
560+ to decline OAS3.0 documents.
561+ If it weren't so, the server
562+ could have responded with the older version
563+ if the OAS3.2 document were not available.
564+
565+ ~~~ http
566+ GET /openapi.yaml HTTP/1.1
567+ Host : example.com
568+ Accept : application/openapi+yaml; version=3.2, application/openapi+yaml; version=3.0;q=0
569+ ~~~
570+
571+ The server responds with the OAS3.2 document.
572+
573+ ~~~ http
574+ HTTP/1.1 200 OK
575+ Content-Type : application/openapi+yaml; version=3.2
576+
577+ openapi : 3.0.0
578+ …
579+ components :
580+ schemas :
581+ Foo :
582+ " $ref " : /foo.yaml
583+ ~~~
584+
585+ The User Agent then requests the /foo.yaml,
586+ but it wants to retrieve a content with the most recent OAS version.
587+
588+ ~~~ http
589+ GET /foo.yaml HTTP/1.1
590+ Host : example.com
591+ Accept : application/openapi+yaml; version=3.2
592+ ~~~
593+
594+ The server processes the Accept header,
595+ and it realizes that foo.yaml is
596+ a JSON Schema document and not an OpenAPI document.
597+
598+ It then replies with the acceptable content.
599+
600+ ~~~ http
601+ HTTP/1.1 406 Not Acceptable
602+ Accept : \
603+ application/whatever+yaml; version=https://json-schema.org/draft/2020-12/schema, \
604+ application/whatever+yaml; version=https://spec.openapis.org/oas/v3.0.4#schema-object
605+ ~~~
606+
607+ The User Agent decides to retry the request
608+ using one of the acceptable media types.
609+ It could have also decided to give up.
610+
611+ ~~~ http
612+ GET /foo.yaml HTTP/1.1
613+ Host : example.com
614+ Accept : \
615+ application/whatever+yaml; version=https://json-schema.org/draft/2020-12/schema
616+ ~~~
617+
618+ Now the server can respond with the JSON Schema representation.
619+
620+ ~~~ http
621+ HTTP/1.1 200 OK
622+ Content-Type : application/whatever+yaml; version=https://json-schema.org/draft/2020-12/schema
623+
624+ " $schema " : " https://json-schema.org/draft/2020-12/schema"
625+ " $id " : " https://example.com/foo.yaml"
626+ oneOf :
627+ - const : it
628+ title : Italian
629+ - const : en
630+ title : English
631+ ~~~
632+
633+ Pros :
634+
635+ - The returned content is exactly what the User Agent requested.
636+
637+ Cons :
638+
639+ - Two requests were needed to retrieve the resource.
640+ - Some User Agents may not be able to handle
641+ the 406 Not Acceptable response and give up.
642+ - Requires a specific Accept value for each possible referenced resource,
643+ which may be difficult to manage.
644+ - Clients may not be able to
645+
646+
348647# Change Log
349648{: numbered="false" removeinrfc="true"}
350649
@@ -364,4 +663,3 @@ RFC EDITOR PLEASE DELETE THIS SECTION.
364663{:numbered="false" removeinrfc="true"}
365664
366665- Support OAS 2.0
367-
0 commit comments