I've implemented an API service using gRPC with protocol buffers and then used grpc-gateway to expose that as a set of REST webservices.
Now I'm getting to the point where I'm having to maintain different versions of the API and I'm stuck.
In my proto file I have a handler like this defined for instance
rpc MerchantGet (MerchantRequest) returns (MerchantResponse) {
option (google.api.http) = {
get: "/v1.1.0/myapi/merchant/{MerchantID}"
};
}
In my Go code of course I then have a function, MerchantGet
, to which GET
actions to /v1.1.0/myapi/merchant/{MerchantID}
are mapped.
Now, let's say I want to add more functionality to the MerchantGet
method and release a new version. I intend to maintain backwards compatibility as per the Semantic Versioning Specification so if I understand correctly that means I can make underlying changes to my MerchantGet
method and have it supersede the older method as long as it does not require different inputs from the 3rd party (MerchantRequest
) or change the response sent to the 3rd party (MerchantResponse
) other than by adding additional fields to the end of the response. (Correct me if I'm wrong in this assumption).
My question is, how do I write proto handlers to serve a method to endpoints of different versions? One option that came to mind would look something as follows:
rpc MerchantGet (MerchantRequest) returns (MerchantResponse) {
option (google.api.http) = {
get: "/v1.6.0/myapi/merchant/{MerchantID}"
additional_bindings {
get: "/v1.5.0/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.4.2/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.4.1/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.4.0/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.3.0/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.2.0/myapi/merchant/{MerchantID}"
}
additional_bindings {
get: "/v1.1.0/myapi/merchant/{MerchantID}"
}
};
}
But surely this can't be the idiomatic way of achieving this? It's certainly not very elegant at all as, with each new minor version or patch, I would have to extend these additional_bindings
to each of my methods (above I'm just using one method as an example).