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

Multiple Different Styles for Query Parameters #1508

Closed
dekryptic opened this issue Mar 14, 2018 · 13 comments
Closed

Multiple Different Styles for Query Parameters #1508

dekryptic opened this issue Mar 14, 2018 · 13 comments
Labels
param serialization Issues related to parameter and/or header serialization

Comments

@dekryptic
Copy link

dekryptic commented Mar 14, 2018

Is it possible to have multiple different styles for query parameters under the same path/operation? This mostly relates to explode. For example, would something like this make sense:

/users?id=3|id=4|id=5&q=1

@ymohdriz
Copy link

ymohdriz commented Mar 15, 2018

Hi @dekryptic ,

Are you talking about passing the array values in the query parameter?
If not, the question you asked is related to http spec not the open api spec. OpenAPI just represents the information about the query parameters.

Please refer https://tools.ietf.org/html/rfc3986#section-3.4

Thanks,
Mohammed

@dekryptic
Copy link
Author

As far as I understand that specification seems to only say that a query begins with a '?' and ends where the URI ends or at a '#' while the OAI spec is more specific.

I basically want to know whether in tooling for the OpenAPI specification, should we allow for mixing of delimiters or enforce constraints when exploding parameters? e.g. mixing pipeDelimited and spaceDelimited.

I don't think this is practically possible, so maybe this should be mentioned this in the docs?

@darrelmiller
Copy link
Member

darrelmiller commented Mar 15, 2018

@dekryptic I don't believe the original example you presented is actually possible with the current spec defintion. The PipeDelimiter and SpaceDelimiter styles only refer to the separator between values, not the delimiter (prefix) between key=value pairs. Therefore, if you have id with style PipeDelimiter and q with style Form you would get,

/users?id=3|4|5&q=1

The Pipe and Space just replace the comma that would be used with style=form. It is probably worth adding a note to the spec to explain that setting explode=true wouldn't cause the pipe character to be used as prefix to the key=name pair.

@dekryptic
Copy link
Author

What about what's mentioned in the Swagger Docs? i.e.

pipeDelimited true n/a n/a /users?id=3|id=4|id=5 n/a

Can you provide an example of mixing explode = true with different styles?

@darrelmiller
Copy link
Member

darrelmiller commented Mar 15, 2018

I hadn't seen those docs. In my opinion that example is wrong. One of the goals of the changes that were made with OAS 3.0 was to try and make the parameter serialization align as closely as possible with RFC6570 without breaking backward compatibility. The Style concept encapsulates two different things from 6570, the separator and the prefix. Characters like the dot, semi-colon and slash are prefixes and commas are separators in 6570. The explode operator (which is concept taken directly from 6570) causes the prefix and key= to be repeated for each value. It isn't related to the separator. So, when you mix styles with different prefixes, the serialization is fairly straightforward.

Consider the template:
{/segments*}{;coords*}{?params*}

where
segments = ["foo","bar"]
coords = {"x": 2 ,"y": 3]
params = {"sort": "up", "view": "minimal" }

you would get:

/foo/bar;x=2;y=3?sort=up&view=minimal

Now only a subset of 6570 is supported currently in OAS, so you can't actual represent the above template yet. However, the serialization rules should attempt to follow 6570 where possible. Note that the ? prefix is special in that the first value gets a ? and subsequent ones get an &. You can also use the & prefix where every value gets the & prefix.

For Pipe and Space delimiting, it should play the same role a comma plays in 6570. i.e. it should separate values when they are not exploded. I see no value in introducing more capability that is incompatible with 6570. Ideally, I would like tooling folks to be able to use existing off the shelf 6570 libraries. I see no reason for us to have to reinvent URL construction code.

@dekryptic
Copy link
Author

dekryptic commented Mar 16, 2018

Thank you for the detailed explanation.

Is the example for

{"in": "path", "style": "label", "explode": false, "schema": {"type": "array"}}

incorrect?

Instead of .blue.black.brown, I'm getting .blue,black,brown using two different URI Template libraries. Here is an example.

@darrelmiller
Copy link
Member

@dekryptic Now that is a mistake in the spec example. You only get .blue.black.brown with explode = true. I will create a PR to fix the spec.

I find this dictionary useful for remembering the behavior of the different operators.

@dekryptic
Copy link
Author

  1. Should the spaceDelimited example be color=blue%20black%20brown and the pipeDelimited example color=blue|black|brown, similar to form?

  2. Also, under the "Style Values" table, should the types for simple be primitive, array, object and the types for spaceDelimited and pipeDelimited be array, object? You have examples for these styles and types in the next section.

@dekryptic
Copy link
Author

dekryptic commented Mar 17, 2018

  1. How do you think tooling should implement deserialization for explode? Do we enforce a constraint that only one exploded query parameter can exist to avoid any conflicts?

@darrelmiller
Copy link
Member

darrelmiller commented Mar 19, 2018

@dekryptic

  1. Yes. Instead of color=blue,black,brown the comma separator is a space or pipe.
  2. For simple, primitive is the same as an array of one. For object the behavior is undefined. I think the behaviour should be the same for pipeDelimited and spaceDelmited.
  3. There should be no reason that multiple exploded parameter values cannot concatenated together. The key is to add the prefix character before each key value pair.

@dekryptic
Copy link
Author

  1. Can you explain what you mean by the behavior for object is undefined with the simple style? I'm confused by the examples:
style explode ... object
simple false ... R,100,G,200,B,150
simple true ... R=100,G=200,B=150
  1. I get that in most cases it shouldn't be an issue. But what if I have this code:
var uriTemplates = require("uri-templates")
let template = new uriTemplates("/{?person*,place*}")
template.fill({person: {name: 'John'}, place: {name: 'The Eiffel Tower'}})

that produces this output:

"/?name=John&name=The%20Eiffel%20Tower"

How would this be deserialized?

@darrelmiller
Copy link
Member

@dekryptic
2. I said undefined, but I sort of lied. OAS doesn't explicitly define what to do with objects that are not exploded, but 6570 does and that is what the example shows. See https://tools.ietf.org/html/rfc6570#section-3.2.2 I'm not really sure we want to specify that behavior because it really isn't very useful.

  1. Welcome to the challenge of 6570. It works pretty well for serialization. It sucks royally for deserialization. It wasn't intended to work for deserialization. We are at the mercy of URL designers to create URLs that don't suck.

@handrews
Copy link
Member

As far as I can tell this conversation was resolved - I know the bug in the spec example was fixed in a PR. I'm going to close this, but if I mentioned something anyone should feel free to comment and I can re-open it (or just feel free to file a new issue with a clear request for a spec change, which may be more likely to get looked at).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
param serialization Issues related to parameter and/or header serialization
Projects
None yet
Development

No branches or pull requests

4 participants