Git Product home page Git Product logo

Comments (4)

commonsensesoftware avatar commonsensesoftware commented on May 24, 2024 7

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:

  1. Version by URL path (ex: /api/v1/foo)
  2. Version by URL query string (ex: /api/foo?api-version=1.0)
  3. Version by HTTP header (ex: api-version: 1.0)
  4. Version by media type negotiation (ex: accept: application/vnd.mycompany.myapp-v2+xml)

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:

  1. Easiest option for all clients to consume (ex: desktop apps, mobile apps, web apps, etc)
  2. Provides a stable URL over time since the query string is not part of the resource path
  3. Easiest option for service authors to integrate without breaking their clients
  4. Flexible option for advanced scenarios where a gateway might need to route a request based on version

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.

from aspnet-api-versioning.

RehanSaeed avatar RehanSaeed commented on May 24, 2024

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 IApiVersionReader seems reasonable. You may want to move away from regular expressions for performance reasons, although you'd probably want to test that first. I'd agree with leaving this as an exercise for the developer to implement IApiVersionReader. I might add an implementation of IApiVersionReader which takes a delegate though.

from aspnet-api-versioning.

commonsensesoftware avatar commonsensesoftware commented on May 24, 2024

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.

from aspnet-api-versioning.

commonsensesoftware avatar commonsensesoftware commented on May 24, 2024

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.

from aspnet-api-versioning.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.