-
Notifications
You must be signed in to change notification settings - Fork 703
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
Versioning using Accept HTTP Header #42
Comments
Great link that summarizes the approaches with the pros and cons of each. I've seen the media type negotation approach before, but had forgotten about it. I would surmise that there are actually 4 common API versioning schemes:
This set of libraries uses option 2 by default. It doesn't necessarily mean it's the best approach as such a statement is highly subjective. Aside from aligning to the Microsoft REST versioning guidelines, I would say that option 2 also has the following benefits:
From a RESTful perspective, I believe that the stable URL constraint is pretty important. Different versions of a resource are not different, logical resources, but rather different representations. The query string never identifies a resource. In that way, the query string and media type methods are similar. While I have obviously have an opinion, the design goals were not to pigeon-hole service authors into my method of API versioning, but instead give them choices with a few out-of-the-box implementations. API versioning using media type negotiation can be supported, but I'm not sure it can be done out-of-the-box. The reason is that there is no established convention or format for the media type value. In your example, the code would have to know how to extract "2" from the "v2" fragment of the header value. All is not lost however. The design of the library abstracts how the raw API version is read from a HTTP request via the IApiVersionReader interface. All of the built-in support goes through this component. There is never any assumptions about how to get the raw API version from a request. It was straightforward to a create a couple of default implementations that understand how to read an API version from a query string or header value. The default readers, however, do not manipulate the extracted value. They assume the value read is in the correct form. An implementation to support API versioning by media type negotiation in Web API might look something like: public class MediaTypeApiVersionReader : IApiVersionReader
{
private const string Pattern = @"-v(\d+(\.\d+)?)\+\S+$";
public string Read( HttpRequestMessage request )
{
// TODO: consider what happens if Accept is provided multiple times or with quality
var mediaType = request.Headers.Accept.Single().MediaType;
var match = Regex.Match( Pattern, mediaType, RegexOptions.RightToLeft );
return match.Success ? match.Groups[1].Value : null;
}
} Now you just need to tell the configuration that you want to read the API version from the request a different way: configuration.AddApiVersioning(
options => options.ApiVersionReader =
new MediaTypeApiVersionReader() ); Everything else about how the library is used is unchanged. If you can think of a standard way of using media types for API versioning, I'm willing to consider its inclusion. For the time being, it is possible to support, but left up to service authors to implement albeit with minimal code. |
I missed the query string as a fourth option. Interestingly I found myself agreeing with your reasoning for it being the default. Unfortunately the vendor tree MIME type standard does not define how a version should be specified. However, I do think that the internet has come to an understanding about how these vnd MIME types can be used as there are numerous articles out there using the same format with the version in the same spot. Your sample code for |
When we just talk service semantics over HTTP, using a vendor tree MIME type makes sense. The realization of that in code by service authors requires more work that most are willing to put in. For example, I completely glossed over the fact that in either of the current ASP.NET stacks, the service author would still have to define custom media type mappings. The example API version reader was in no way meant to represent production code, which could also be some optimized parsing routing or a dictionary that maps content type to version. I considered just having a callback method in the options or having a DelegatingApiVersionReader class, but it didn't seem it would be used all that often. Furthermore, creating a class with a single method is not a huge effort and it assists in the intention-revealing readability of the code. |
Re-opening this issue so that it can be linked to the forthcoming PR. After quite a bit of thought, there is a way to make this work standard and out-of-the-box using a media type parameter. While defining custom media types would be technically possible, the platform setup requires more effort than most are willing to put in. Furthermore, I think we would agree that although there is nothing wrong with defining custom media types, we would want to avoid using them. See #70 for an overview of how it will work. |
There are three main versioning strategies that people use (See link). I don't see versioning by the Accept HTTP header listed as being supported on the Wiki page:
Accept: application/vnd.mycompany.myapp-v2+xml
The text was updated successfully, but these errors were encountered: