OpenAPI-Specification icon indicating copy to clipboard operation
OpenAPI-Specification copied to clipboard

Feature Request: $ref for Operation Object

Open fcasad opened this issue 2 years ago • 9 comments

The current OAS 3.1 spec allows the use of $ref for "Path Item Object" but not for "Operation Object". Is there a reason for this? It would be quite nice to be able to break down a large doc at the operation level. This could also be useful for describing APIs that are composed together (ie describing an API gateway).

fcasad avatar Apr 29 '22 16:04 fcasad

If I understand your request correctly you could already do that, like this:

paths:
 '/path1':
    get:
      '$ref': 'operations/path1-get.yaml'
    post:
      '$ref': 'operations/path1-post.yaml'

# ....

edit: the above example would probably work with most of the tooling. However Reference is not explicitly listed as the Type for an operation here: https://spec.openapis.org/oas/v3.1.0#path-item-object so that is what should be updated.

cebe avatar May 02 '22 12:05 cebe

Yep, that is exactly what I want to do.
It does work with the tooling I'm using, but my team was concerned since this isn't mentioned in the spec.

fcasad avatar May 02 '22 20:05 fcasad

It's not currently supported by the spec, and @cebe's example is unfortunately invalid.

webron avatar May 02 '22 21:05 webron

@webron thanks. Are you aware of any technical reasoning against supporting this? And if not, what would it take to add to the spec?

fcasad avatar May 02 '22 21:05 fcasad

We try to be specific about what can be referenced as (especially now), we now include anything that can be referenced under components as reusable items.

Individual operations don't tend to be reused, and as far as I recall, we haven't had too many requests for it. Since operations tend to be specific to their path, describing methods such as GET, POST, PUT often accept/return entities that are specific to their paths - and reusing those just isn't all that common. Perhaps in the future if we support a more extensive level of reference templating, it would make more sense. Until then, I'm not convinced there's a good use case for adding support for it.

webron avatar May 02 '22 21:05 webron

Appreciate the insight!

I agree a potential #/components/operations is probably not particularly helpful for reuse, but by that token is #/components/pathItems?

Btw, my goal isn't to reuse an operation within the same OAS document, but to split up a large doc into multiple files at the operation level. And also potentially ref those operations into other docs. I can resolve the refs at build time using something like this, which will produce a valid spec in the end. Would this be the preferred approach for my use case?

fcasad avatar May 02 '22 22:05 fcasad

The reuse of Path Item Object was introduced a while back, and taking it out now is a bit of a challenge. I was surprised to see it being used, but it really is. You can argue and say that if we support one, we should support the other, which is completely fair. That said, we're trying to be conscious about adding additional complexity to the spec. For your use case, I'd say that splitting path items into separate files could give you at least some level of ability to split up large docs as a single path item object can have a finite number of operations.

You can definitely do your own magic with pre/post-processing docs, as long as the final doc is valid (you wouldn't be the first). Specifically the usage of $refs with the suggested dereferencer may or may not work. Reasons are: an OpenAPI definition is not a json schema, and OAS references are not exactly JSON Schema references (though for your own preprocessing, you can decide them to be whatever you want as they are out of scope for the spec).

webron avatar May 02 '22 22:05 webron

Ok, it's understandable to try and avoid increasing the spec surface area. But splitting at the path item level isn't really ideal to me. I'll consider alternatives...

fcasad avatar May 02 '22 23:05 fcasad

Hello, I have another similar case for the sake of completeness: On RESTful APIs, the method OPTION should be available on every paths and thus would require to copy/paste a lot in the OpenAPI document. However, except in case of required authentication/authorization, even me don't really see it useful to describe it in OpenAPI...

mikky-is avatar Jul 07 '22 02:07 mikky-is

Hello @webron, I would like to ask that this feature be reconsidered as well, and I think not having this feature is a serious oversight as I'll explain below.

Right now it is the case that Path objects are able to be replaced with a reference even though they are not "reusable", so I suggest that the aim of the references not be reusability so much as splitting up larger OpenAPI specification documents into more manageable chunks. This includes the reusability you speak of, because the objectives are the same (shorten the doc). If path objects can be referenced it makes no sense that operations can not be, since these are normally tied to different API endpoints on the backend. In fact operations make a lot more sense than the path being able to be referenced for this very reason. Trying to lump the external link generation for combined GET and POST operations requires literally creating a new backend API endpoint that returns a composite group of service specs around a base path. Since the operation is the base unit of the API endpoint, it actually makes more sense to have an operation ref than a path ref.

I have a use case where I have several endpoints for every data type that use the same filters (a huge number of them) and putting them in the same file as the top level specification causes timeout issues in the main file. I was looking for a way to move the filter parameters out of the top level specification, but the capabilities are not there. You can't reference parameter groups, just individual parameters, which doesn't help at all. So there is simply no way that I can see to accomplish what I need to do with the specification as it stands now.

What I wanted to do was to have is either parameter group references (not supported) or a query parameter on each of the filter supporting endpoints (?schema) that would render the schema for that API endpoint (in this case Django Views) then link to that reference in the top level file so that the top level file would be a lot more concise, and you could technically follow the references for path operations that you needed, seeing as how people are focused on designing for the endpoints, not the path objects.

If there is another way to achieve what I am trying to do please let me know? If what I expect is the case and there is no way to actually shorten this file without substantial changes to the backend endpoints then this should be a priority. It is one thing to argue against a feature if there is another way that is more canonical, but quite another when there is no other way to achieve the objectives in an efficient way.

adrianwebb avatar Oct 13 '22 03:10 adrianwebb

A huge part of the value of OpenAPI is not repeating yourself. We generate clients, servers, docs... all that with a simple and fairly conceptually tight format. But having a large interface split across several files now requires that you repeat each path in the top level specification file. This is super bad. Requiring extra tooling doesn't make it better.

djMax avatar Oct 17 '22 11:10 djMax

Re-visiting since a few other folks asked for this...

I've now seen several large OpenAPI documents in the wild that have made this (non-canonical) use of $ref. One public example is Box, see here. @webron any chance it might still be considered?

fcasad avatar Oct 17 '22 22:10 fcasad

Folks interested in this issue may be interested in the more general discussion of referencing that is now just getting started.

handrews avatar Nov 06 '22 23:11 handrews

We are interested in the same issue, any news?

vbauer avatar Dec 29 '22 14:12 vbauer

What about this:

paths:
  /path1:
    $ref: "file1.yaml#/paths/%2Fpath1"
  /path2:
    $ref: "file2.yaml#/paths/%2Fpath2"

it is working. But is it allowed as per the Spec ?

[EDIT]: ok I recognized with openapi: "3.0.3" it works. With openapi: "3.1.3" it is not. :(

aminabromand avatar Aug 27 '23 06:08 aminabromand

@aminabromand

[EDIT]: ok I recognized with openapi: "3.0.3" it works. With openapi: "3.1.3" it is not. :(

This is likely to be a tooling issue you should open with your tool vendor, as the spec is the same in both versions in this regard.

handrews avatar Aug 29 '23 16:08 handrews

@vbauer there is talk of completely re-doing the referencing model in OpenAPI 4 (a.k.a. "Moonwalk") - here's a summary of the discussion from our last call before the late-summer break. With added opinionating from me.

As far as currently, since (unlike everywhere else), "$ref" in a path item object can combine with adjacent fields as long as the same field is not both adjacent to the "$ref" and in the target, you can sort-of re-use operations by making path items with one operation each and then "$ref"-ing them together. Which gets a little complex because you can only have one "$ref" per path item object so you'd kind of have to layer the on one at a time, but it could be done. I think.

handrews avatar Aug 29 '23 16:08 handrews