OAI / OpenAPI-Specification

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

'produces' in endpoint does not deal with dynamic conversion #1260

Closed orubel closed 7 years ago

orubel commented 7 years ago

as 'produces' exists in endpoint, what does one do if backend dynamically handles the conversion; ie. if I request with content-type xml, it converts to resource to XML.

MikeRalphson commented 7 years ago

produces at the operation level (in version 2.0) is an array, so multiple values can be held. If the client sends an Accept header containing one of those values, the assumption is that the API (backend) will honour that and produce the corresponding Content-Type. produces (either at the default root level, or at the operation level) shoudl list all of the Content-Types the API is capable of producing, either for the API as a whole, or that operation specifically.

This is regardless of the Content-Type of any submitted body parameter. Just because you submit xml there is no reason not to request a json response if the API supports it. If your API does not honour the standard Accept header, then you should still list all of the relevant Content-Types in the produces array and document the fact that the input Content-Type will dictate the output Content-Type.

orubel commented 7 years ago

Just because you submit xml there is no reason not to request a json response if the API supports

Ah but try to do this via other languages or via Curl. The content-type is what 'sets' the return type. Sure one CAN do alot of things but one has to create a 'standard expectation' and the 'standard expectation' is that what is requested is what will be sent.

It would be like ordering a burger but expecting a pizza. Sure you may have wanted a pizza but you but then you should have ordered a pizza. The user can SEE the expectations, you can dynamically convert, they just have to pick one or the other... they cant have their cake and eat it too.

One can due everything on the backend but then we would spend all our time processing and be bogged down. Those millions of request would be delivered in hours instead of seconds (exaggerations of course)... but you have to pick and choose battles.

And this is something that can be left to the user. They can see the requirements and pick one. Not all languages and tools support this thinking you are purporting.

orubel commented 7 years ago

I guess what I am saying in a drawn out way it is : Simplify. This is not a standard, this is not supported and its overly complex. Just support the 90% of 'return content-type that is requested'.

Everything else is up to client/end user.

MikeRalphson commented 7 years ago

Ah but try to do this via other languages or via Curl. The content-type is what 'sets' the return type

Not in the HTTP specification it isn't. The Accept header is what controls what response Content-Type should be sent. It absolutely is a standard, and is supported everywhere now.

Imagine an image conversion API, the Content-Type of the input cannot specify the desired Content-Type of the response, or no conversion would ever happen.

In other news, I am now hungry. :smile:

darrelmiller commented 7 years ago

I'm going to go a step further than @MikeRalphson . To be pedantic, HTTP does not provide a standard way for a client to request a particular media type. The request Accept header is used to allow a client to indicate what media types it understands and use a q value to indicate a preference. The server gets to choose which representation to return. There is absolutely no guarantee that the server will respect the client preferences. If an API designer wants to allow a client to be explicit about the format that is returned then they should create a resource per representation format.

orubel commented 7 years ago

Ah sorry. Its how I code it. One header, one conversion, one return type. Simple.

@darrelmiller Yes, but you are adding to overhead. Isn't the purpose to engineering to provide simple elegant answers. This is overly complex.

If you can deduce on 90% of requests what the response is from content-type... do so. And let the others fall through the cracks and be handled through a forward to a service or by the client/end user.

Reduces my processing by 3-5%.

The scenario you are discussing is rare anyway.

darrelmiller commented 7 years ago

And just to clarify one thing, because I'm not exactly sure about what is being said here. Using a Content-Type header as a request header to do anything other than declare the media type of the request body is invalid.

orubel commented 7 years ago

No it isn't. Its logical. In 90% of cases what is being requested is what is being returned.

If I request with 'application/json', 90% of the time I will want back JSON. Reason being is that I am working with JSON.

If I request with 'application/xml', 90% of the time I will want back XML. Reason being is that I am working with XML.

Its deductive reasoning.

The ACCEPT header covers those RARE occasions when we want to send back something that doesn't match what we are requesting with.

What I'm saying is... ignore it. Let the end user handle those conversions.

A properly built system will FORWARD an API call on the backend to a service to handle something like that or the client/end user will be responsible for a conversion where they send JSON but want the JSON to be converted to XML.

There are PLENTY of Javascript JSON to XML (and Vice-versa) converters

darrelmiller commented 7 years ago

RFC 7231:

The "Content-Type" header field indicates the media type of the associated representation: either the representation enclosed in the message payload or the selected representation, as determined by the message semantics.

The content-type is not used to negotiate a representation format to be returned by the server.

orubel commented 7 years ago

Regardless. Its deductive reasoning and human behaviour and its works greater than 90% of the time

I haven't had to touch the ACCEPT header for years.

Like I said, it people send a burger order, they RARELY expect a pizza.

A spec (like most things in computer science) is a guideline... and you have to know when to use it and when to break it. And this is one of those times when it is more useful to break it.

If you want to keep processing ACCEPT, thats great. Its just additional overhead.

MikeRalphson commented 7 years ago

If I order a burger over a fax, I don't want a faxed picture of a burger back. I want a burger.

In OAS terms, I think a specification/vendor extension which you define as meaning the request Content-Type controls the response Content-Type is all you will be able to do for versions up to and including 3.0.0

darrelmiller commented 7 years ago

@orubel A spec is not just a guideline. It is an enabler of common understanding. When you redefine the meaning of things it makes everyone's life more difficult.

orubel commented 7 years ago

@MikeRalphson To use your analogy, if you ordered a burger over a fax, you ordered a receipt for the burger sent back via fax. Don't be silly.

@DarrelMiller Many specs do not take into consideration changing environments, rules, requirements.

Take for instance the API Pattern. It was designed in the 1970's for centralized architectures... never for distributed architectures. But people still use the same pattern to day and have created architectural cross cutting concerns in distributed architectures violating AOP principles, dropping threads, creating unsynchronized data, etc. RedHat & IBM actually wrote articles about this 3 years after I initially brought it up (https://developers.redhat.com/blog/2017/01/05/architectural-cross-cutting-concerns-of-cloud-native-applications/). Netflix API manager stated 'This fixes everything we are currently having issues with'

So I will have to politely disagree. Specs are merely a guideline... a path for us to follow until we find we can improve upon them and write a BETTER path.

By reducing code and reducing processing, how does that make peoples lives hard? That actually simplifies. Simplification makes peoples lives easier. What you have defined is harder and more complex than it has to be

orubel commented 7 years ago

Regardless, change is a natural thing. Take it or leave it. I dont care. Was just trying to help.

darrelmiller commented 7 years ago

If you want to change the HTTP spec there is a working group that guides that work. https://lists.w3.org/Archives/Public/ietf-http-wg/ Until the HTTP spec changes, I will continue to use the specification as defined to ensure interoperability.

darrelmiller commented 7 years ago

Let me add that I do appreciate you trying to help and voice your perspective. However, that perspective would be much more valuable if it were on the version of the spec we have been working on for the last 18 months, rather than debating features that were obsoleted 12 months ago.

orubel commented 7 years ago

Heh. Well thank you for the suggestion. For now I'm going to continue to see them as a 'very good suggestion'... thats how everyone in enterprises see them when they are trying to reduce processing power, get better throughput, improve processes. etc.

I rarely have this kind of a religious debate so I won't go further. I leave specs to those who need to be told what to do.

orubel commented 7 years ago

@darrelmiller Alot of your documentation hasn't been updated and still says v2 so don't blame me. And if I didn't find it properly, I was just going off github.

orubel commented 7 years ago

Also for the record, it didn't help being snarky. Just because you don't know me doesn't mean you should be impolite. It makes a lasting impression.

orubel commented 7 years ago

By the way, just looked at a couple implementations and people merely add the 'accept' header in controller/method on rare occasions they want to send different type (rather than handling for EVERY request).

Again, people still don't need to send ACCEPT and you don't need to deal with it. It is just rare occasion that content-type will not dictate the return type. ie. When ordering a burger, people rarely expect a taco.

darrelmiller commented 7 years ago

The resource identifier identifies what is being ordered. I don't see a way to fit Content-Type into your analogy.

orubel commented 7 years ago

Content-type specifies what is being sent; if what is being sent is JSON. 9/10 times, what is being returned is JSON. Thus ACCEPT is redundant in 90% of cases

For those times that it is needed, you set at controller/method. For example if I use content-type JSON but want back PDF, at the controller/method, I just set the header.

Simple.

For those rare occasions, it WOULD have to show in the docs.

What I am stating though is that it is not necessary or required. If all of your docs return exactly what is requested, then you only need one consolidated request/response FORMAT for endpoint

darrelmiller commented 7 years ago

And what do you do for the 90% of requests that are GETs?

orubel commented 7 years ago

Also, ACCEPT is the RESPONSE format... not so much a 'resource identifier'. This is the header that is given when the RESPONSE outputs. The resource has long since been parsed by the controller and munged into whatever is going to be output by the RESPONSE.

This is why we may be getting a bit confused. I look at these from more of a communication layer

orubel commented 7 years ago

Same thing. Standardize. May not be 'proper' but you can now send data and automate in a standardized way. Once you can easily automate and standardize your procedure and code, you'd be amazed and how much time you can shave off

darrelmiller commented 7 years ago

I'm really not sure what you believe you can automate that is not possible by using HTTP the way it was intended.

orubel commented 7 years ago

heh... rather than sending and parsing two headers, or one header... just sending only one header? With every request? It simplifies. Its faster. Its easier. Its less code. and it does the same work.

And for the 10% of case where it doesn't, you add it to the backend code so that it fills in the blanks

darrelmiller commented 7 years ago

Don't send any and just deal with the format the server sends you. Any API that allows you to choose between arbitrary formats like XML and JSON is missing the point of media types anyway.

orubel commented 7 years ago

The user has expectations and it is easier to know what is being sent. It provides the starting point for formatting the output as well

If we were triangulating, we would need two headers to guess the third. Since there are only two data points, we can guess the second after we have the first.

Saying don't send any is obviously sarcasm... but I'm not taking it to heart :)

orubel commented 7 years ago

There is no choosing between formats. The end user picks their output by sending the data in the format that they want it returned in

Why would someone send in JSON if they expect it in XML. Thats just silly ;)

darrelmiller commented 7 years ago

Except for when you are doing a GET, OPTIONS or DELETE. And the assumption that you get back what you send is wrong for every single HTML form on the Web.

orubel commented 7 years ago

heh. definitely some fudging going on. But again. Less headers, less code, less parsing, fast and more scalable :)

We avoid all those checks and just say send only one header and read only one header... and don't even bother reading anything else. Saves ALOT of parsing and processing

And we get the same thing done only ALOT FASTER!

orubel commented 7 years ago

AND YES... it breaks some rules. But to scale things and improve, we always do. Thats how we improve

If nothing else, I gave you something to scratch your head on. Thats it.