Skip to content

OpenAPI.next: Allow recursive paths #647

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

Closed
IvanGoncharov opened this issue Apr 11, 2016 · 14 comments
Closed

OpenAPI.next: Allow recursive paths #647

IvanGoncharov opened this issue Apr 11, 2016 · 14 comments

Comments

@IvanGoncharov
Copy link
Contributor

In OpenAPI 2.0 paths like /user/{userId}/ and /user/{userId}/history considered as totally separate paths with nothing in common even path parameters. Moreover, you can't define global parameters.
I propose to allow for recursive paths, it would look like that:

paths:
  '/':
    parameters:
        - in: query
          name: globalParam
          type: string
    '/user/{userId}/':
       parameters:
          - in: path
            name: userId
            type: string
       get:
           #....
       '/history':
          get:
             #...

Pros:

  • non-breaking change, you can still define old style with /user/{userId}/ and /user/{userId}/history as separate paths.
  • allow for global parameters similar to moved reusable definitions under a single element #633, but without breaking change and JSON pointer stay nice and short #/parameters/<name>.
  • remove duplication for path parameters
  • at least party address @webron concern about adding description into pathObject see added description field #632 (comment)
  • doesn't conflict with possible extensions to path template mechanism, since recursive paths just concatenate.
  • if things like consume, produce, responses will be added into pathObject, remove a lot of duplication.
  • Easy to implement validation in JSON Schema using patternProperties.

Cons:

  • force tooling to process recursion and parameter merging
@fehguy
Copy link
Contributor

fehguy commented Apr 11, 2016

I think this abuses the path key too much. Better to keep at top-level, or at path item level.

@IvanGoncharov
Copy link
Contributor Author

I think this abuses the path key too much. Better to keep at top-level, or at path item level.

@fehguy Can you please elaborate.
Do you concern with human-readability of spec?
Or support in tooling ?

@fehguy
Copy link
Contributor

fehguy commented Apr 11, 2016

yes to all. It's an overload of a path name (is parameters a legal path?), is weird to read, and will cause tooling hassles. Suggest using top-level, parameters, or path-item level to accomplish a nearly identical goal.

@IvanGoncharov
Copy link
Contributor Author

@fehguy

is parameters a legal path?

It's easy, only keys what starts with / is paths.

will cause tooling hassles

I agree with this one. It requires tool author to write additional 50-100 SLOC.

@IvanGoncharov
Copy link
Contributor Author

It's not an argument, just thing to note.
Such functionality supported in WADL, Google Discovery, I/O Docs, RAML and probably other formats.
So it looks like industry-wide practice, so it worth to consider.

But I don't say OpenAPI should automatically borrow from other formats, especially from WADL.

@darrelmiller
Copy link
Member

@IvanGoncharov I think it is a fairly fundamental difference in the way APIs are described. Admittedly paths are naturally hierarchical, and getting the reuse ability for free is nice. However, it doesn't help when it comes to re-use of query parameter descriptions. Personally I find deep paths are often a design smell in APIs and I'm not sure we should be encouraging them. If other design formats support that style of API description and you find that more natural, then take advantage of it. I'm not sure the goal should be to make all API description languages work the same way.

@webron
Copy link
Member

webron commented Apr 12, 2016

This can lead to some nasty structures too - potentially describing the entire API as one big deeply nested tree. Putting aside the issues it may cause tools, it would be harder for human-readability as well.

This also potentially puts us back to 1.2 and earlier versions with the organization concept of resources. One of the goals of moving to tags for grouping was to allow the flexibility there.

I don't find the benefits enough, especially with the supported reusability.

@IvanGoncharov
Copy link
Contributor Author

I'm not sure the goal should be to make all API description languages work the same way.

Totally agree, it's part of the evolutionary process.
But I think common practices should be evaluated for possible accepting into OpenAPI.

This can lead to some nasty structures too - potentially describing the entire API as one big deeply nested tree.

I see that hierarchical structures in JSON/YAMl are a question of personal taste.
Personally, I agree with @darrelmiller:

Admittedly paths are naturally hierarchical

But I don't want to turn this into some kind of bike-shed discussion.
If someone will have any technical concerns I would be happy to address them.

My proposal is to leave this issue open for few weeks to maybe have some feedback from the community.
And then make official technical committee decision about it.

@DavidBiesack
Copy link
Contributor

From a human factors perspective, nesting is normally the preferred structure. Originally, that was what I preferred about RAML over Swagger. But with OAI, the content is verbose enough that nesting does not help - there is too much info to fit nicely into a single screen unless the tools to a really good job with collapsing sections. Constantly expanding/collapsing gets pretty tedious.

I agree reusing parameters is useful and a desired feature. One must be careful with adopting nesting because you to clarify exactly what is inherited from the parent. All parameters with in: path? I suppose. less likely for parameters with other values for in, and then you may need a way to override an inherited parameter, which adds complexity. What else do we gain by nesting? I can't think of much else.

(We actually have an internal tool that we're integrating into our Swagger editor which can add a missing path parameter by finding a matching in: path parameter via other paths.)

Looking outside API descriptions, I think this is somewhat analogous to object modeling in OO languages. Inheritance was cool, but then it got abused, and composition became a preferred way to model things. Languages which only support single inheritance are less powerful/expressive than those that allow composition/mixins/traits. Nesting paths feels analogous to OO inheritance.

See also OAI/Overlay-Specification#34 for an alternative to nesting -- use parameter sets.

@claudio-viola
Copy link

claudio-viola commented Mar 16, 2017

I too think this should be part of the spec. Surprised its not.
Replicating common sense shouldn't be something to discuss or argue about.

@pduchesne
Copy link

This looks to me like a very useful feature, and i'm not sure why it was closed. Is it abandoned ?

Anyway, allow me to expose a legitimate usecase that only this nesting feature would fulfill (as fas as I understand): service composition. I'd happy to know if there's another way to implement it.

Let's say we have two independent services, A and B, each coming with their respective service descriptions serviceA.yaml, serviceB.yaml embedded at their roots.
These services can potentially be deployed as standalone applications, on arbitrary URL subpaths, e.g. http://foo.com/serviceA, with its description then sitting at http://foo.com/serviceA/serviceA.yaml and looking like

servers:
  - description: Service A
    url: .
paths:
    ...

Then there's a need to deploy a service C, that composes A and B under two subpaths :
http://foo.com/serviceC/serviceA and http://foo.com/serviceC/serviceB.
It should be possible to declare this composition in http://foo.com/serviceC/serviceC.yaml, containing something like :

servers:
  - description: Composed Service C
    url: .
paths:
  /serviceA:
    $ref: 'serviceA/serviceA.yaml'
  /serviceB:
    $ref: 'serviceB/serviceB.yaml'

Can you comment on this usecase ?

@handrews
Copy link
Member

handrews commented Dec 5, 2018

@pduchesne I'm pretty sure your use case is different from the original use case in the issue.

The issue was about being able to nest path descriptions under each other to arbitrary depths to factor out common path prefixes. You are just combining paths from two sources, but at the same level (your end result is equivalent to manually copying everything from A's paths: and everything from B's paths: under C's paths:, where C's prefix of http://foo.com/serviceC can be set by the normal OAS base path functionality).

@pduchesne
Copy link

yes, I understand that the original issue is about potentially arbitrary deep nesting, while my example is about factoring out the first level of the path.
However, I still don't see how, with the current spec, I can express the fact that I want to import all paths elements from serviceA under a subpath in serviceC, and all path elements from serviceB under another subpath. In my understanding, being able to factor out subpaths serviceA and serviceB to import a set of paths elements under them is one way to solve it.
If you think this is feasible, can you elaborate on how you would do this ?

@handrews
Copy link
Member

handrews commented Dec 5, 2018

@pduchesne if you have a new question different from the one raised in this issue, you should open a new issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants