swagger-ui: `Example.externalValue` is not displayed

Example Swagger/OpenAPI definition

openapi: 3.0.0

paths:
  /:
    post:
      requestBody:
        content:
          image/png:
            schema:
              type: string
              format: binary
            examples:
              KittenImage:
                externalValue: "https://placekitten.com/200/300"
      responses:
        "200":
          description: OK!

Current behavior

image

Expected behavior

I should be able to use the externally-referenced image as an example value for my endpoint (provided that Swagger UI is able to reach the resource).

Additional context or thoughts

#5427.

About this issue

  • Original URL
  • State: open
  • Created 5 years ago
  • Reactions: 17
  • Comments: 31 (6 by maintainers)

Most upvoted comments

I have the same problem. I prefer to keep my examples in external .json files (same with models) so as not to clutter the spec itself too much. Any idea where this is in the priority stack please?

The documentation says that there is possible to use externalValue. Please update the documentation or fix a bug.

I don’t know if this is the appropriate issue, but instead of binary image, I simply want external JSON to display. Is this already planned?

openapi: 3.0.2
info:
  description: 'myapp'
  version: '2.0.0'
  title: 'myapp 2.0 Rest API'
servers:
  - url: http://localhost:8080/rest
    description: Local Environment
  - url: https://app-dev.myapp.foo/rest
    description: Development Environment
paths:
  /rest/companies:
    get:
      summary: 'Get all companies'
      description: 'foo'
      produces:
        - 'application/json'
      responses:
        '200':
          description: 'successful operation'
          content:
            application/json:
              schema:
                type: 'array'
                items:
                  $ref: '#/components/schemas/Company'
              examples:
                jsonObject:
                  summary: This is an example in Company
                  externalValue: 'https://static.myapp.foo/examples/rest_companies_example.json
components:
  schemas:
    Company:
      type: 'object'
      properties:
        id:
          type: 'integer'
          format: 'int64'
        name:
          type: 'string'

I build my self a quick hack, that works for me for now

https://github.com/swagger-api/swagger-ui/compare/47b992f51c36a85648442c4a246466f83339c9c3...clouless:feature/examplesExternalValue

Push. How has this not been fixed in 2 and a half years?!

Workaround with wrapComponents

Sample openapi.yaml

openapi: 3.0.1
info:
  title: Swagger Petstore
  description: 'This is a sample server Petstore server'
  version: 1.0.0
servers:
- url: https://petstore.swagger.io/v2
- url: http://petstore.swagger.io/v2
paths:
  /router/rest:
    get:
      summary: test
      operationId: test
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
              examples:
                success:
                  summary: JSON example
                  value: Loading...
                  externalValue: 'example/test.json'
            application/xml:
              schema:
                type: object
                xml:
                  name: xml
              examples:
                success:
                  summary: XML example
                  value: Loading...
                  externalValue: 'example/test.xml'

Add custom plugin to index.html

// Examples map
const examples = {};

// Custom plugin for logic that happens before the response element is created
const CustomPlugin = () => {
  return {
    wrapComponents: {
      response: (Original, { React, oas3Actions, oas3Selectors }) => (props) => {
        const contentType = oas3Selectors.responseContentType(props.path, props.method)
        const externalValue = props.response.getIn(['content', contentType, 'examples', props.activeExamplesKey, 'externalValue'])
        // Check if externalValue field exists
        if (externalValue) {
          // Check if examples map already contains externalValue key
          if (examples[externalValue]) {
            // Set example value directly from examples map
            props.response = props.response.setIn(['content', contentType, 'examples', props.activeExamplesKey, 'value'], examples[externalValue])
          } else {
            // Download external file
            fetch(externalValue)
            .then(res => res.text())
            .then(data => {
              // Put downloaded file content into the examples map
              examples[externalValue] = data
              // Simulate select another example action
              oas3Actions.setActiveExamplesMember({
                "name": 'fake',
                "pathMethod": [props.path, props.method],
                "contextType": "responses",
                "contextName": props.code
              })
              // Reselect this example
              oas3Actions.setActiveExamplesMember({
                "name": props.activeExamplesKey,
                "pathMethod": [props.path, props.method],
                "contextType": "responses",
                "contextName": props.code
              })
            })
            .catch(e => console.error(e))
          }
        }
        return React.createElement(Original, props)
      }
    }
  }
}

window.onload = function() {
  const ui = SwaggerUIBundle({
    url: 'openapi.yaml',
    dom_id: '#swagger-ui',
    deepLinking: true,
    presets: [
      SwaggerUIBundle.presets.apis,
      SwaggerUIStandalonePreset
    ],
    plugins: [
      SwaggerUIBundle.plugins.DownloadUrl,
      // Add custom plugin
      CustomPlugin
    ],
    layout: "StandaloneLayout"
  });

  window.ui = ui;
};

Has someone found a way to bypass this issue and somehow use externalValue?

It is literally all there, in my initial pr at https://github.com/swagger-api/swagger-js/pull/2013

It is just missing the base64 part and some tests.

@tim-lai @char0n This is a really low hanging fruit. Can you please give this some priority on “your internal backlog”

In addition, this is not a swagger-ui issue. It arises because of wrong resolution / normalization in the swagger-js package.

Anything that can be done to get this on the roadmap?

Push. How has this not been fixed in 2 and a half years?!

If you have time have a look at swagger-api/swagger-js#1978 and finish it up. Currently I have no time to work on it.

I dont have any experience with JS and that’s not the point i was trying to convey to be honest. Im not asking you to make it work in your free time, but the least that should be done is a deprecation of that option with a fat warning or a flat out removal so people dont waste their time trying to get this to work, if you don’t intend to do anything about it any time soon

@tim-lai I think this is only partially a swagger-ui issue! I have tried to integrate externalValue examples (from params, requestBody, response) into the sample generation process. I realized that this value is not resolved, I think swagger-js should resolve this just like it resolves refs.

Else ways I will implement some resolver that will fetch the raw value hosted behind the externalValue url.

Can we get this fixed please? You have done a great job on introducing multiple example values for the multiple ways that an API endpoint can be called - now please let us also use them in your UI!

Any workaround for this issue? Please share the details when we should expect the fix.