Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default responses #563

Open
fehguy opened this issue Feb 10, 2016 · 18 comments
Open

Add default responses #563

fehguy opened this issue Feb 10, 2016 · 18 comments
Labels
re-use: globals/defaults Default or global components that can be overridden in some way

Comments

@fehguy
Copy link
Contributor

fehguy commented Feb 10, 2016

Currently, every single operation must declare its' own responses. This causes a whole bunch of duplication, which would be better served by having a top-level responses section in the spec. Like the security construct, operations could override the default responses on their own.

@fehguy
Copy link
Contributor Author

fehguy commented Feb 10, 2016

parent issue #560

@darrelmiller
Copy link
Member

An alternative solution that could potentially also address this concern is to introduce the notion of a globally defined array of OperationTypes. In the same way that there can be redundancy in the responses that an operation returns, there can also be redundancy in the parameters that the operations accept.

By allowing the definition of a type of operation with the parameters and responses defined, we are creating the HTTP equivalent of a function signature definition, aka delegate.

An example of this might be in an issue tracking system where there following operations exist:

/api/issues/closed{?createdSince,limit,keywords}
/api/issues/active{?createdSince,limit,keywords}

In both cases the result is a list of issues and the same set of parameters are valid.

One additional benefit of taking this approach is that it becomes easier to describe hypermedia systems that use link relation types. Consider the following example,

{ 
   "project" :"My software product",
   "links" : [
             { "rel" : "issues", "href": "/api/issues/closed{?createdSince,limit,keywords}", "title" : "closed" }
             { "rel" : "issues", "href": "/api/issues/active{?createdSince,limit,keywords}", "title" : "Active" }
       ]
}

The OpenAPI document could describe the expected behaviour when an issues type of operation is accessed.

@dilipkrish
Copy link
Contributor

👍 to @darrelmiller's suggestion.

@mpnally
Copy link

mpnally commented Feb 21, 2016

@darrelmiller You can do this example today, like this:

swagger: 2.0
...
x-operationTypes:
  IssueList:
    parameters:
      ..
    get:
      ..
    post:
      ..
paths:
  /api/issues/closed:
    $ref: '#/x-operationTypes/IssueList'
  /api/issues/active:
    $ref: '#/x-operationTypes/IssueList'

If the paths have parameters in them, you can still do this sort of thing in YAML, but not in JSON. Since this is already possible in OAS today, is it really necessary to add new features? Less is more.

@darrelmiller
Copy link
Member

@mpnally That's definitely an interesting workaround even with the JSON limitation.

However, there is additional value to being explicit about the operation type. When it comes to creating client code, explicit knowledge of the similarity between the interaction mechanism for different resources can be leveraged to significantly reduce redundant client code. I have had considerable success in building client libraries where I create a client side class that implements the Operation Type behavior and then re-use that class for multiple resources.

This lends itself well to a hypermedia scenario where the link relation type can tell the client which operation type to use and the resource identifier is contained in the response. This allows client code to successfully interact with resources it previously did not know about even when there is a non-trivial interaction model.

I agree that adding unnecessary features is good design choice. However, in this case, I think the web architecture has proven that the notion of link relation types is a useful one and we have an opportunity to model that important web concept in OpenApi.

@dolmen
Copy link

dolmen commented Mar 1, 2016

@fehguy In Swagger 2.0 there is already a top-level responses object that is used for global responses definitions.

@webron
Copy link
Member

webron commented Mar 1, 2016

@dolmen the top level responses are not used as global responses but as reusable responses to which you can reference from operations.

@dolmen
Copy link

dolmen commented Mar 2, 2016

@webron Yes. My use of "global" adjective was not right. But my point is that @fehguy proposal conflicts with an existing use of the responses property in Swagger 2.0.

@fehguy
Copy link
Contributor Author

fehguy commented Mar 14, 2016

Good feedback on this. Two thoughts.

First, @darrelmiller's suggestion is interesting as it can be used to compose many different types into an operation. It could become very verbose still, as one could potentially have dozens of constructs in the path identifier. I'll keep thinking about how that could work.

Next, the notion of top-level definitions in the current 2.0 spec is a little confusing. For example as @dolmen pointed out, there is a responses section, but they're not really responses--they are responseDefinitions. But we have a top-level accepts which applies to all operations defined in the spec.

I think these are different considerations. To address the 2nd item, in general, we have definitions and implementations at the root of the specification. Think of definitions as items which are always referenced elsewhere, and implementations as instances of requirements in the definition itself.

Some definitions:

  • definitions
  • securityDefinitions
  • parameters
  • responses

Some implementations:

  • paths
  • accepts/consumes
  • info
  • security
  • host
  • schemes
  • basePaths
  • tags

This is very confusing. The purpose for named definitions was that the schema could be used to ensure that all items under the, say, parameters definition were valid.

To simplify the structure, and to make room for reusable components as well as a hierarchial structure, I propose the following:

  • The specification always supports a top-down overlay. This means that items defined at the top-level of the specification shall apply to all subordinate operations, except when overridden.
  • The specification defines an explicit section for schemas, with the goal of reuse

Proposed structural changes

# implementations
info:
  # info object

# some implementations omitted for clarity
basePath:
  # basePath
tags:
  # - tag object
paths:
  # paths object
parameters:
  # parameters which apply to all operations
responses:
  # responses which apply to all operations
responseHeaders:
  # headers to be returned in all responses
security:
  # security requirements which apply to all operations
# definitions
schemas:
  definitions:
    # payload definition objects
  parameters:
    # parameters objects
  responses:
    # responses objects
  responseHeaders:
    # headers returned in responses
  security:
    # security definitions

In the proposed structure, we now have a single schemas section which allows us to put all reusable components in a single section. It also makes it possible to have the new parameters and responses section, which will give maximum reusability and readability.

If a top-level response is defined, say with 404 as the key, then an operation can override it by defining a new 404 response definition. There is no deletion of top-level items inside an operation.

@ePaul
Copy link
Contributor

ePaul commented Mar 14, 2016

@fehguy For the naming, I would prefer definitions as the top level, and schemas for payload schema definitions under that, instead of the other way around.

definitions:
  schemas:
    # payload schema definition objects
  parameters:
    # parameter definition objects
  responses:
    # response objects
  ...

I guess we could also have operations objects in there (as proposed in #577).

@IvanGoncharov
Copy link
Contributor

@ePaul IMHO it very bad decision to change semantic of existing keyword. One thing is to put it in a different place of hierarchy and totally another is to change it mining. And it's not only for Swagger 2.0 migration, because Swagger borrowed it from JSON Schema, see this.

@fehguy I agree with @ePaul that schemas is confusing because of similarity with JSON Schema.
Let's wait maybe someone come up with a better alternative.

@SandyChapman
Copy link

I kind of like the name schemas. It implies that that portion of the API description corresponds to something validatable using JSON Schema.

@ePaul
Copy link
Contributor

ePaul commented Mar 23, 2016

@SandyChapman Yes, but that validatability (does that word exist?) works only for JSON stuff which is transmitted in body parameters or responses, i.e. which corresponds to model definitions. That was my reason for definitions/schemas. I understand that people don't like reusing the definitions name which was formerly used for just schema definitions, though.

@DavidBiesack
Copy link

Please also see the discussion on OAI/Overlay-Specification#34 which discusses creating reusable parameter sets.

I see all these as related topics: how to get effective reuse of OAS constructs, either through composition and some form of template or protoypes mechanism, then providing a way to "mixin" those reusable elements, be they parameter definitions, responses, links, etc.

While much can be done with $ref, I would much prefer to see structural notation that conveys the abstraction. It would be nice to have a uniform way of defining and invoking mixins.

@michael-o
Copy link

michael-o commented Oct 18, 2019

A simple usecase, status code which apply to all paths: 401, 403, 500, 502, 503, 504. They -- in most cases -- don't require any response body. Maybe 500.

@mxmlnglt
Copy link

mxmlnglt commented Jul 8, 2021

A simple usecase, status code which apply to all paths: 401, 403, 500, 502, 503, 504. They -- in most cases -- don' require any response body. Maybe 500.

I second that. (it's 2021)

@omgkotofey
Copy link

+1

@kscheirer
Copy link

I will take a look at if/how overlays can solve this problem. This is part of determining whether overlay spec is sufficient, so I won't comment on other solutions now.

For @michael-o 's question

  1. Using explicit http response codes
{
  "overlay": "1.0.0",
  "info": {
    "title": "Default Response Codes Overlay",
    "version": "1.0.0"
  },
  "actions": [
    {
      "target": "info",
      "update": {
        "x-overlay-applied": "default-response-codes"
      }
    },
    {
      "description": "Add default responses to all operations",
      "target": "paths.*.*",
      "update": {
        "responses": {
          "401": {
            "description": "Unauthorized"
          },
          "403": {
            "description": "Forbidden"
          },
          "500": {
            "description": "Internal Server Error"
          },
          "502": {
            "description": "Bad Gateway"
          },
          "503": {
            "description": "Service Unavailable"
          },
          "504": {
            "description": "Gateway Timeout"
          }
        }
      }
    }
  ]
}
  1. Using 'default' response, https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#responsesObject
{
  "overlay": "1.0.0",
  "info": {
    "title": "Default Response Overlay",
    "version": "1.0.0"
  },
  "actions": [
    {
      "target": "info",
      "update": {
        "x-overlay-applied": "default-response"
      }
    },
    {
      "description": "Add default response to all operations",
      "target": "paths.*.*",
      "update": {
        "responses": {
          "default": {
            "description": "unexpected error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "code": {
                      "type": "integer",
                      "format": "int32"
                    },
                    "message": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  ]
}

@handrews handrews added re-use: globals/defaults Default or global components that can be overridden in some way and removed re-use labels Jan 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
re-use: globals/defaults Default or global components that can be overridden in some way
Projects
None yet
Development

No branches or pull requests