From 98d6d44b9e9bcfe9c7d65d1d7f2f956c2d8766f0 Mon Sep 17 00:00:00 2001 From: Jason Harmon Date: Fri, 8 Jan 2016 12:39:21 -0600 Subject: [PATCH 1/5] Refined guidelines for external file reuse --- guidelines/REUSE.md | 130 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 19 deletions(-) diff --git a/guidelines/REUSE.md b/guidelines/REUSE.md index 13d4cecb42..3f7299fde6 100644 --- a/guidelines/REUSE.md +++ b/guidelines/REUSE.md @@ -1,38 +1,65 @@ # Reuse Philosophy + We encourage reuse and patterns through references. ## What is reusable + The following types are reusable, as defined by the spec: -* Operations * Parameters -* Responses * Models (or Schema Objects in general) +* Responses +* Operations (_Operations can only be referenced externally_) ## Reuse strategy + When reusing components in an API design, a pointer is created from the definition to target design. The references are maintained in the structure, and can be updated by modifying the source definitions. This is different from a "copy on design" approach where references are injected into the design itself. The reuse technique is transparent between JSON or YAML and is lossless when converting between the two. -YAML anchors are technically allowed but break the general reuse strategy in Swagger, since anchors are "injected" into a single document. They are not recommended. +YAML anchors are technically allowed but break the general reuse strategy in OpenAPI Specification, since anchors are "injected" into a single document. They are not recommended. -Referenes can be made either inside the Swagger definition file or to external files. References are done using [JSON Reference](http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03). +Referenes can be made either internal to the OpenApi Specification file or to external files. ## Techniques ### Guidelines for Referencing +Whether you reference definitions internally or externally, you can never override or change their definitions from the referring location. The definitions can only be used as-is. + +#### Internal references + When referencing internally, the target references have designated locations: -* Parameters -> `parameters` -* Responses -> `responses` -* Models (and general Schema Objects) -> `definitions` +* Parameters -> `#/parameters` +* Responses -> `#/responses` +* Models (and general Schema Objects) -> `#/definitions` + +All references are canonical and must be a qualified [JSON Pointer, per RFC6901](http://tools.ietf.org/html/rfc6901). For example, simply referencing a model `Pet` is not allowed, even if there are no other definitions of it in the file. + +_Example from https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/json/petstore.json_ +``` json + "200": { + "description": "pet response", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/Pet" + } + } +``` + +#### External references -Operations can only be referenced externally. +If your referenced file contains only one root-level definition, you can refer to the file directly. -An example for an internal reference - `#/definitions/MyModel`. All references are canonical and must be a qualified [JSON Pointer](http://tools.ietf.org/html/rfc6901). For example, simply referencing `MyModel` is not allowed, even if there are no other definitions of it in the file. +To reference the example below: -When referencing externally, use a valid URI as the reference value. If your referenced file contains only one definition that should be used, you can refer to the file directly. For example: +`"$ref": "definitions/Model.json""` + +or + +`"$ref": "https://my.company.com/definitions/Model.json"`. _Assuming file https://my.company.com/definitions/Model.json_ ```json @@ -47,7 +74,16 @@ _Assuming file https://my.company.com/definitions/Model.json_ } ``` -The reference would be `https://my.company.com/definitions/Model.json`. +To reference `Model` in the example below: + +_Note this approach potentially combines URL, JSON Reference, and JSON Pointer_ + +`"$ref": "definitions/models.json#/models/Model"` + + or + +`"$ref": "https://my.company.com/definitions/models.json#/models/Model"` + _Assuming file https://my.company.com/definitions/models.json_ ```json @@ -74,12 +110,52 @@ _Assuming file https://my.company.com/definitions/models.json_ } ``` -The reference to the `Model` model would be `https://my.company.com/definitions/models.json#/models/Model`. Make sure you include the full path to the model itself, including its containers if needed. +#### External by relative reference -Whether you reference definitions internally or externally, you can never override or change their definitions from the referring location. The definitions can only be used as-is. +All external relative references should follow the [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) specification. -### Definitions -Reuse schema definitions by creating a repository of definitions. This is done by simply hosting a file or set of files for commonly used definitions across a company or organization. In the case of multiple files, the models can be referenced directly as such: +Per the JSON Reference spec: + +> If the URI contained in the JSON Reference value is a relative URI, +then the base URI resolution MUST be calculated according to +[RFC3986], section 5.2. Resolution is performed relative to the +referring document. + +_Example from https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v2.0/json/petstore-separate/spec/swagger.json_ + +``` json +"responses": { + "default": { + "description": "unexpected error", + "schema": { + "$ref": "../common/Error.json" + } + } +} +``` + +External references may also utilize [JSON Pointer](http://tools.ietf.org/html/rfc6901) to reference properties within the relative external file. + +_Example from https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v2.0/json/petstore-separate/spec/swagger.json_ +``` json +"parameters": [ + { + "$ref": "parameters.json#/tagsParam" + }, + { + "$ref": "parameters.json#/limitsParam" + } +] +``` + + +#### External by URL + +External files can be hosted on an HTTP server (rather than the local file system). + +One risk of this approach is that environment specific issues could arise if DNS is not taken into account (as the reference can only contain one hostname). + +Resolution of URLs should follow [RFC3986](https://tools.ietf.org/html/rfc3986). _Assuming file https://my.company.com/definitions/Model.json_ ```json @@ -92,14 +168,14 @@ _Assuming file https://my.company.com/definitions/Model.json_ "format": "int64" }, "tag": { - "description": "a complex, shared property. Note the absolute reference", + "description": "A complex, shared property. Note the absolute reference", "$ref": "https://my.company.com/definitions/Tag.json" } } } ``` -For a single file, you can package the definitions in an object: +External references may also utilize a URL + JSON Pointer to reference properties within the external file. _Assuming file https://my.company.com/definitions/models.json_ ```json @@ -133,8 +209,20 @@ _Assuming file https://my.company.com/definitions/models.json_ ``` +### Definitions + +Reuse schema definitions by creating a repository of definitions. This is done by simply hosting a file or set of files for commonly used definitions across a company or organization. + +Refer to [External references](#external-references) for referencing strategies. + + ### Parameters -Similar to model schemas, you can create a repository of `parameters` to describe the common entities that appear throughout a set of systems. Using the same technique as above, you can host on either a single or multiple files. For simplicity, the example below assumes a single file. + +Similar to model schemas, you can create a repository of `parameters` to describe the common entities that appear throughout a set of systems. + +Refer to [External references](#external-references) for referencing strategies. + +Using the same technique as above, you can host on either a single or multiple files. For simplicity, the example below assumes a single file. _Assuming file https://my.company.com/parameters/parameters.json_ @@ -205,8 +293,11 @@ To include these parameters, you would need to add them individually as such: ``` ### Operations + Again, Operations can be shared across files. Although the reusability of operations will be less than with Parameters and models. For this example, we will share a common `health` resource so that all APIs can reference it: +Refer to [External references](#external-references) for additional referencing strategies. + ```json { "/health": { @@ -246,7 +337,8 @@ Which points to the reference in the `operations.json` file: Remember, you cannot override the definitions, but in this case, you can add additional operations on the same path level. ### Responses -Just like the other objects, responses can be reused as well. + +Refer to [External references](#external-references) for additional referencing strategies. Assume the file `responses.json`: From 70c72a34ee81b780b4eeaf77d1bd8163400142b5 Mon Sep 17 00:00:00 2001 From: Jason Harmon Date: Fri, 8 Jan 2016 15:36:33 -0600 Subject: [PATCH 2/5] Removing implementation constraints from reuse --- guidelines/REUSE.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/guidelines/REUSE.md b/guidelines/REUSE.md index 3f7299fde6..7df3927c21 100644 --- a/guidelines/REUSE.md +++ b/guidelines/REUSE.md @@ -391,6 +391,3 @@ You can refer to it from a response definition: } } ``` - -### Constraints -* Referenced objects must be to JSON structures. YAML reuse structures may be supported in a future version. From dc58a156e87b300442b97c322e1e596a7e511fe6 Mon Sep 17 00:00:00 2001 From: Jason Harmon Date: Wed, 13 Jan 2016 15:15:03 -0600 Subject: [PATCH 3/5] Refactoring based on PR discussion --- guidelines/REUSE.md | 115 +++++++++++--------------------------------- 1 file changed, 27 insertions(+), 88 deletions(-) diff --git a/guidelines/REUSE.md b/guidelines/REUSE.md index 7df3927c21..ad72a43139 100644 --- a/guidelines/REUSE.md +++ b/guidelines/REUSE.md @@ -9,33 +9,40 @@ The following types are reusable, as defined by the spec: * Parameters * Models (or Schema Objects in general) * Responses -* Operations (_Operations can only be referenced externally_) +* Operations (_Operations can only be remote references_) ## Reuse strategy -When reusing components in an API design, a pointer is created from the definition to target design. The references are maintained in the structure, and can be updated by modifying the source definitions. This is different from a "copy on design" approach where references are injected into the design itself. +When reusing components in an API design, a reference is created from the definition to target entity. The references are maintained in the structure, and can be updated by modifying the source definitions. This is different from a "copy on design" approach where references are injected into the design itself. The reuse technique is transparent between JSON or YAML and is lossless when converting between the two. YAML anchors are technically allowed but break the general reuse strategy in OpenAPI Specification, since anchors are "injected" into a single document. They are not recommended. -Referenes can be made either internal to the OpenApi Specification file or to external files. - ## Techniques ### Guidelines for Referencing -Whether you reference definitions internally or externally, you can never override or change their definitions from the referring location. The definitions can only be used as-is. +All references should follow the [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) specification. + +JSON Reference provides guidance on the resolution of references, notably: + +> If the URI contained in the JSON Reference value is a relative URI, +then the base URI resolution MUST be calculated according to +[RFC3986], section 5.2. Resolution is performed relative to the +referring document. + +Whether you reference definitions locally or remote, you can never override or change their definitions from the referring location. The definitions can only be used as-is. -#### Internal references +#### Local references -When referencing internally, the target references have designated locations: +When referencing locally (within the current document), the target references should follow the conventions, as defined by the spec: * Parameters -> `#/parameters` * Responses -> `#/responses` -* Models (and general Schema Objects) -> `#/definitions` +* Definitions (Models/Schema) -> `#/definitions` -All references are canonical and must be a qualified [JSON Pointer, per RFC6901](http://tools.ietf.org/html/rfc6901). For example, simply referencing a model `Pet` is not allowed, even if there are no other definitions of it in the file. +An example of a local definition reference: _Example from https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/json/petstore.json_ ``` json @@ -49,77 +56,11 @@ _Example from https://github.com/OAI/OpenAPI-Specification/blob/master/examples/ } ``` -#### External references +#### Remote references -If your referenced file contains only one root-level definition, you can refer to the file directly. +##### Relative path -To reference the example below: - -`"$ref": "definitions/Model.json""` - -or - -`"$ref": "https://my.company.com/definitions/Model.json"`. - -_Assuming file https://my.company.com/definitions/Model.json_ -```json -{ - "description": "A simple model", - "type": "object", - "properties": { - "id": { - "type": "integer" - } - } -} -``` - -To reference `Model` in the example below: - -_Note this approach potentially combines URL, JSON Reference, and JSON Pointer_ - -`"$ref": "definitions/models.json#/models/Model"` - - or - -`"$ref": "https://my.company.com/definitions/models.json#/models/Model"` - - -_Assuming file https://my.company.com/definitions/models.json_ -```json -{ - "models": { - "Model": { - "description": "A simple model", - "type": "object", - "properties": { - "id": { - "type": "integer" - } - }, - "Tag": { - "description": "A tag entity in the system", - "type": "object", - "properties": { - "name": { - "type": "string" - } - } - } - } -} -``` - -#### External by relative reference - -All external relative references should follow the [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) specification. - -Per the JSON Reference spec: - -> If the URI contained in the JSON Reference value is a relative URI, -then the base URI resolution MUST be calculated according to -[RFC3986], section 5.2. Resolution is performed relative to the -referring document. +Files can be referred to in relative paths to the current document. _Example from https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v2.0/json/petstore-separate/spec/swagger.json_ @@ -134,7 +75,7 @@ _Example from https://github.com/OAI/OpenAPI-Specification/tree/master/examples/ } ``` -External references may also utilize [JSON Pointer](http://tools.ietf.org/html/rfc6901) to reference properties within the relative external file. +Remote references may also reference properties within the relative remote file. _Example from https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v2.0/json/petstore-separate/spec/swagger.json_ ``` json @@ -149,14 +90,12 @@ _Example from https://github.com/OAI/OpenAPI-Specification/tree/master/examples/ ``` -#### External by URL +##### URL -External files can be hosted on an HTTP server (rather than the local file system). +Remote files can be hosted on an HTTP server (rather than the local file system). One risk of this approach is that environment specific issues could arise if DNS is not taken into account (as the reference can only contain one hostname). -Resolution of URLs should follow [RFC3986](https://tools.ietf.org/html/rfc3986). - _Assuming file https://my.company.com/definitions/Model.json_ ```json { @@ -175,7 +114,7 @@ _Assuming file https://my.company.com/definitions/Model.json_ } ``` -External references may also utilize a URL + JSON Pointer to reference properties within the external file. +Remote references may also reference properties within the remote file. _Assuming file https://my.company.com/definitions/models.json_ ```json @@ -213,14 +152,14 @@ _Assuming file https://my.company.com/definitions/models.json_ Reuse schema definitions by creating a repository of definitions. This is done by simply hosting a file or set of files for commonly used definitions across a company or organization. -Refer to [External references](#external-references) for referencing strategies. +Refer to [Guidelines for Referencing](#guidelines-for-referencing) for referencing strategies. ### Parameters Similar to model schemas, you can create a repository of `parameters` to describe the common entities that appear throughout a set of systems. -Refer to [External references](#external-references) for referencing strategies. +Refer to [Guidelines for Referencing](#guidelines-for-referencing) for referencing strategies. Using the same technique as above, you can host on either a single or multiple files. For simplicity, the example below assumes a single file. @@ -296,7 +235,7 @@ To include these parameters, you would need to add them individually as such: Again, Operations can be shared across files. Although the reusability of operations will be less than with Parameters and models. For this example, we will share a common `health` resource so that all APIs can reference it: -Refer to [External references](#external-references) for additional referencing strategies. +Refer to [Guidelines for Referencing](#guidelines-for-referencing) for referencing strategies. ```json { @@ -338,7 +277,7 @@ Remember, you cannot override the definitions, but in this case, you can add add ### Responses -Refer to [External references](#external-references) for additional referencing strategies. +Refer to [Guidelines for Referencing](#guidelines-for-referencing) for referencing strategies. Assume the file `responses.json`: From e622056ae2491ccf38d28cc6e80406edf4ad4133 Mon Sep 17 00:00:00 2001 From: Jason Harmon Date: Wed, 13 Jan 2016 21:07:49 -0600 Subject: [PATCH 4/5] Content fixes for 'Reuse Strategy' --- guidelines/REUSE.md | 50 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/guidelines/REUSE.md b/guidelines/REUSE.md index ad72a43139..a25899b537 100644 --- a/guidelines/REUSE.md +++ b/guidelines/REUSE.md @@ -7,17 +7,54 @@ We encourage reuse and patterns through references. The following types are reusable, as defined by the spec: * Parameters -* Models (or Schema Objects in general) +* Models (_or Schema Objects in general_) * Responses * Operations (_Operations can only be remote references_) ## Reuse strategy -When reusing components in an API design, a reference is created from the definition to target entity. The references are maintained in the structure, and can be updated by modifying the source definitions. This is different from a "copy on design" approach where references are injected into the design itself. +When authoring API design documents, common object definitions can be utilized to avoid duplication. For example, imagine multiple path definitions that each share a common path parameter, or a common response structure. The OpenAPI specification allows reuse of common object definitions through the use of "references". -The reuse technique is transparent between JSON or YAML and is lossless when converting between the two. +A reference a construct in your API design document that indicates "the content for this portion of the document is defined elsewhere". To create a reference, at the location in your document where you want to reuse some other definition, create an object that has a `$ref` property whose value is a URI pointing to where the definition is (more on this in later sections). -YAML anchors are technically allowed but break the general reuse strategy in OpenAPI Specification, since anchors are "injected" into a single document. They are not recommended. +OpenAPI's provides reference capabilities using the [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) specification. + +### JSON Example + +``` json +{ + // ... + definitions: { + Person: { + type: 'object', + properties: { + friends: { + type: 'array', + items: { + $ref: '#/definitions/Person' + } + } + } + } + } +} +``` + +### YAML Example + +``` yaml +# ... +definitions: + Person: + type: object + properties: + friends: + type: array + items: + $ref: '#/definitions/Person' +``` + +Note: YAML has a very similar feature, [YAML anchors](http://yaml.org/spec/1.2/spec.html#id2765878). Examples from this point will only be in JSON, using JSON References. ## Techniques @@ -46,6 +83,7 @@ An example of a local definition reference: _Example from https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v2.0/json/petstore.json_ ``` json + // ... "200": { "description": "pet response", "schema": { @@ -65,6 +103,7 @@ Files can be referred to in relative paths to the current document. _Example from https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v2.0/json/petstore-separate/spec/swagger.json_ ``` json +// ... "responses": { "default": { "description": "unexpected error", @@ -79,6 +118,7 @@ Remote references may also reference properties within the relative remote file. _Example from https://github.com/OAI/OpenAPI-Specification/tree/master/examples/v2.0/json/petstore-separate/spec/swagger.json_ ``` json +// ... "parameters": [ { "$ref": "parameters.json#/tagsParam" @@ -233,7 +273,7 @@ To include these parameters, you would need to add them individually as such: ### Operations -Again, Operations can be shared across files. Although the reusability of operations will be less than with Parameters and models. For this example, we will share a common `health` resource so that all APIs can reference it: +Again, Operations can be shared across files. Although the reusability of operations will be less than with Parameters and Definitions. For this example, we will share a common `health` resource so that all APIs can reference it: Refer to [Guidelines for Referencing](#guidelines-for-referencing) for referencing strategies. From 5669bd4676709dac6bb382739dc618f5c41866fc Mon Sep 17 00:00:00 2001 From: jasonh-n-austin Date: Thu, 14 Jan 2016 11:28:43 -0600 Subject: [PATCH 5/5] More content fixes --- guidelines/REUSE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guidelines/REUSE.md b/guidelines/REUSE.md index a25899b537..2d3192c262 100644 --- a/guidelines/REUSE.md +++ b/guidelines/REUSE.md @@ -15,13 +15,13 @@ The following types are reusable, as defined by the spec: When authoring API design documents, common object definitions can be utilized to avoid duplication. For example, imagine multiple path definitions that each share a common path parameter, or a common response structure. The OpenAPI specification allows reuse of common object definitions through the use of "references". -A reference a construct in your API design document that indicates "the content for this portion of the document is defined elsewhere". To create a reference, at the location in your document where you want to reuse some other definition, create an object that has a `$ref` property whose value is a URI pointing to where the definition is (more on this in later sections). +A reference is a construct in your API design document that indicates "the content for this portion of the document is defined elsewhere". To create a reference, at the location in your document where you want to reuse some other definition, create an object that has a `$ref` property whose value is a URI pointing to where the definition is (more on this in later sections). OpenAPI's provides reference capabilities using the [JSON Reference](https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03) specification. ### JSON Example -``` json +``` js { // ... definitions: {