OAI / OpenAPI-Specification

The OpenAPI Specification Repository
https://openapis.org
Apache License 2.0
29.02k stars 9.07k forks source link

Make Paths Object Optional #1045

Closed tedepstein closed 4 years ago

tedepstein commented 7 years ago

The Paths Object is required to be present in the OpenAPI Object.

This makes it awkward to create an OpenAPI spec that serves as a "catalog" of reusable components. This is already a common usage pattern in OpenAPI 2.0, and we expect it will be even more common with OpenAPI 3.0, with the introduction of the Components Object, and new types of reusable definitions contained within it.

It's possible to create a catalog file, but you have to do one of two things:

  1. Use JSON's empty object syntax, because there is no explicit empty object syntax in YAML. This works, but it's awkward, and is just a way of getting around the requirement. to have a Paths Object. Here's a 2.0 example:
    
    ---
    swagger: "2.0"
    info:
    version: 1.0.0
    title: Uber Schema Definitions

This is a component file, used by the Uber API specification.

The paths property is required, so we use curly braces to denote an empty object,

meaning there are no path items defined in this file.

paths: {}

The definitions section contains a set of named Schema Objects. Each object

describes a reusable data type. We refer to these using a $ref property, with a

JSON Reference value that resolves to the definition.

definitions:

PriceEstimate: type: object properties: product_id: type: string description: Unique identifier representing a specific product for a given latitude & longitude. For example, uberX in San Francisco will have a different product_id than uberX in Los Angeles ...



OR...

2. Use a YAML or JSON file format that is not valid OpenAPI, specifically for catalog files.  This means the file can't be processed by standard OpenAPI documentation tools, code generators and other processors, if those tools include schema validation (or the equivalent). And it means we don't have an implementation-independent standard format for catalog files.

So I would argue for making `paths` optional.
webron commented 7 years ago

This is actually not different than 2.0. The spec is intended to document APIs, not catalogs of reusable objects. We can change that definition, but that's what it is. A file without paths does not describe an API.

The reason why paths may be empty is explained in the spec (otherwise, we would have enforced at least one path).

If you want to create a catalog, the only part of the spec you really need is the components, however, 'external' references don't have to adhere to the same structure of the spec (for several reasons).

tedepstein commented 7 years ago

This is actually not different than 2.0. The spec is intended to document APIs, not catalogs of reusable objects. We can change that definition, but that's what it is. A file without paths does not describe an API.

Well, here's what's weighing against that distinction:

So the question is, what's the value of requiring the Paths object?

Please correct me if you really think those two curly braces are the only thing keeping this Pandora's box from unleashing eternal chaos. And of course I can live with it as-is. I'm just having a hard time seeing a downside to this.

webron commented 7 years ago

Again, this is about repurposing the spec. It's meant to describe APIs, not catalogs of objects that can be used in APIs. The paths is not the only required items that is not necessarily important, the info can impose unnecessary things as well. And what would be the meaning of a combination of just servers and components?

The components is meant as a convenience. We could have said just as well that you can only reference definitions outside an API definition (and I'm not suggesting that).

I disagree with your point about the ACL. A non-existing paths would tell me this is a broken API definition, not a filtered one.

I get the benefits of using a similar structure. However, I feel we should revisit it only after the upcoming release. If other @OAI/tdc members feel differently, please say so.

CharlieReitzel commented 5 years ago

The simple approach, I think, is to define components in separate source files that hew to the mutually supported subset of JSON Schema and refer to these schema elements from my Open API documents as needed.

However, this discussion has clarified an issue for me. Consider the relationship between WSDL and XML Schema. WSDL is an XML vocabulary that describes services (requests w/ responses). When WSDL needs to define the contents of request or response bodies, it does so by incorporating the XML Schema standard by reference.

Contrast this the relationship between Open API and JSON Schema. In essence, Open API includes and restricts (and, occasionally, alters!) JSON Schema. And this is where it goes wrong, imo. Open API needs to "suck it up" and deal with entire JSON Schema spec - at least for any schema definitions an API author needs.

It took a while for XML Schema tooling to get all the way there. But it's been there for years and it works well. By splintering the schema spec between Open API and JSON Schema proper, it is actually slowing down progress on tooling and making it more difficult to define APIs out of re-usable components (does anyone not do that?!?).

darrelmiller commented 5 years ago

deal with entire JSON Schema spec - at least for any schema definitions an API author needs.

Welcome to 4 years of debating what that includes ,while JSON Schema goes through multiple revisions. There are a bunch of people trying to make happen what you are suggesting but it involves trade-offs that different people have different opinions about.

handrews commented 5 years ago

@CharlieReitzel but we're getting closer! @philsturgeon refers to this as the "superset-subset" problem. The draft of JSON Schema that will come out this month (seriously- I've put up some of the last few JSON Schema spec PRs today, just need to add some better examples now) allows defining extension vocabularies and restricting usage in machine-readable ways.

As @darrelmiller knows, we (myself and @philsturgeon) are now working with the TSC and others (hi @mkistler!) on how this could be used with OpenAPI.

In fairness to the OpenAPI folks, JSON Schema was practically abandoned for most of the time while OAS 3 was being developed, and while it had been revived into active development shortly before OAS 3.0 was published, we had not gotten far enough along to help converge things and OAS 3.0 rightly chose not to wait on what was then a relatively untested new JSON Schema spec team. We've made a lot of progress on both projects since then and I am optimistic about OAS 3.1 and JSON Schema draft 2019-08 working together much more smoothly.

CharlieReitzel commented 5 years ago

@darrelmiller @handrews I understand that what I'm asking for is much (much!) easier said than done. All the hard work, which includes all the discussion and consensus building, is very much appreciated.

I like schema and contract based development. So I'm a big fan of what you all are doing.

hkosova commented 4 years ago

In OAS 3.1, paths are optional.

https://github.com/OAI/OpenAPI-Specification/releases/tag/3.1.0-rc0

An OpenAPI Document now requires at least one of paths, components or webhooks to exist at the top level. While previous versions required paths, now a valid OpenAPI Document can describe only webhooks, or even only reusable components.

Can this be closed?

philsturgeon commented 4 years ago

It can be! 🎊

shefaliv commented 4 years ago

@hkosova In order to leverage this, do I update the yml file to include "openapi: 3.1.0"? The samples in this repo seem to be quite outdated, so I'm not sure what example to use. 3.1.0 doesn't seem to be allowed in the 5.0.0-beta JAR file or the version installed via brew.

philsturgeon commented 4 years ago

3.1.0 is currently a release candidate and not much tooling (any?) supports it yet. When it’s released, you’ll need to change the version at the top yes and paths will be optional.

deitch commented 6 months ago

OpenAPI spec that serves as a "catalog" of reusable components

I am curious as to how you resolved this. paths is indeed optional, but as far as I can tell, most code generation tools seem to ignore anything in components that is not in paths somewhere.

handrews commented 6 months ago

most code generation tools seem to ignore anything in components that is not in paths somewhere.

The point here is for Components-only documents to be used as a library that can be shared by multiple API Descriptions. You still need to $ref the components from you paths or webhooks for them to be part of a specific API's description. If you $ref two components in a Components-only document with 100 components in it, you wouldn't want code generators to waste time and space with the other 98 components!

deitch commented 6 months ago

Oh I see what you're saying. By making paths optional, you can have an openapi spec-compliant document that only contains components (like schemas). It now is valid.

Before passing it through any generators, though, it would be referenced by other docs that do include paths.

Components-only document with 100 components in it, you wouldn't want code generators to waste time and space with the other 98 components!

Actually, I might. If I've defined the schemas, I want the types. Maybe I'm planning on using them in a future API that isn't ready yet, but internally I want to use the types. Maybe I use them now for other purposes (eg data marshaling into message buses) that eventually will end up in REST API as well. Either way, openapi docs are the standard for API, and have to include content (ie message) structures to do so. Why wouldn't the message structures be valuable on their own?

handrews commented 6 months ago

@deitch at this point you're getting into very subjective calls as to what is useful. OpenAPI Descriptions describe an API starting from an entry document, and only the components used (meaning reachable from) that entry point are part of that API's description.

There's nothing stopping a tool from implementing support for generating code from unreferenced components, though. That's a tool developer question, not a spec question.

deitch commented 6 months ago

getting into very subjective calls as to what is useful

Definitely. No argument there.

There's nothing stopping a tool from implementing support for generating code from unreferenced components, though. That's a tool developer question, not a spec question

I would agree with you, if not for this one point in the spec:

All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object.

I think that stops tooling from even looking at things, even if they wanted to. If it says something like, "All objects defined within the components object are not required to have any effect on the API unless they are explicitly referenced from properties outside the components object", then it would be optional, and become purely a tooling discussion.

CharlieReitzel commented 6 months ago

@deitch at this point you're getting into very subjective calls as to what is useful. OpenAPI Descriptions describe an API starting from an entry document, and only the components used (meaning reachable from) that entry point are part of that API's description.

Definitely not one size fits all. Different approaches are useful/appropriate, depending on circumstances. OpenAPI is used by a lot of people, now, for all kinds of applications. So it's better not to be too opinionated.

There's nothing stopping a tool from implementing support for generating code from unreferenced components, though. That's a tool developer question, not a spec question.

Yes, exactly.

Example use case: Generating a "common value objects" library for any given programming language(s) from the components spec. The library can be generated, versioned to match the spec version, and pulled in as a dependency to API implementations that include the components schema in their API spec. By matching the library version, the various consuming APIs know that, at least, their common object definitions match. This is an enterprise development scenario, where multiple teams work on multiple, mutually interacting services to deliver a larger product.

deitch commented 6 months ago

The library can be generated, versioned to match the spec version, and pulled in as a dependency to API implementations that include the components schema in their API spec

I am dealing with several use cases right now that are fairly similar to this (each in its own way).

Any thoughts on that part of the spec I referenced above?

All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object

Some tools do have options to ignore this, but the spec seems to indicate they should not, rather than may not?

CharlieReitzel commented 6 months ago

Open API 3.1.0 says

All objects defined within the components object will have no effect on the API unless they are explicitly referenced from properties outside the components object

Charlie Reitzel says:

The library can be generated, versioned to match the spec version, and pulled in as a dependency to API implementations that include the components schema in their API spec.

@deitch Avi Deitch says:

Some tools do have options to ignore this, but the spec seems to indicate they should not, rather than may not? Any thoughts on that part of the spec I referenced above?

I see no inconsistency between the use cases we're talking about and that clause about the Components section of the spec.

Here's one way to look at it: if a specific API includes the components document by reference and a resulting implementation includes the library as a dependency, if there are no references in any of the paths to objects defined in the document, then the library can be left off at runtime without any effect - positive or negative.

Not certain, but perhaps the purpose of the clause is to avoid side-effects of document inclusion and to help API authors to better understand the nature of document inclusion.

A good API generator / lint tool might even recommend excluding any components documents lacking references to objects defined within. This is analogous to dependency analysis tools that identify unused dependencies for an application written in a given programming language.

deitch commented 6 months ago

A good API generator / lint tool might even recommend excluding any components documents lacking references to objects defined within. This is analogous to dependency analysis tools that identify unused dependencies for an application written in a given programming language.

My concern was that the spec as written would discourage even the option. I don't view it as a lint error, but as you wrote, there are lots of use cases. If your use case is, "I want a tight API based on paths", then it is a linter error. In others, not so much.

Good conversation, though,