Question
Kurro Lopez · Oct 30, 2019

API RESTful Version

Hello,

We need to create a versioning of an existing API, so we going to set a default version (so far) for current connections to version 1

My first attempt is:

XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
    <Route Url="(?i)/check" Method="GET" Call="CheckApi"/>
    <Route Url="(?i)/getcustomer" Method="POST" Call="GetCustomerDefault"/>
    <Route Url="(?i)/revoke" Method="DELETE" Call="RevokeDefault"/>
    <Route Url="(?i)/:version/getcustomer" Method="POST" Call="GetCustomer"/>
    <Route Url="(?i)/:version/revoke" Method="DELETE" Call="Revoke"/>
</Routes>
}
 
Parameter DEFAULTVERSION = 1;
 
Parameter CURRENTVERSION = 2;
/// Get customer info (API version default)
ClassMethod GetCustomerDefault() As %Status
{
    quit ..GetCustomer(..#DEFAULTVERSION)
}
 
ClassMethod GetCustomer(pVersion As %IntegerAs %Status
{
    // This is the code for all version. Get the Id and pass into the message
    ........
    quit $$$OK
}
 
 

 

Also, I have a parameter called DEFAULTVERSION with value 1

By this way, the newer calls will have the version number and response according the version of API

The URL will be:

apiserver.com/api/2/getCustomer

I'm checking if the version is less than a CURRENTVERSION, the call is fine

According to a new especification, the URL will be "api/v2/getCustomer", before it was an integer, and now will be a string.

 

How can I check if this parameter is well formed (v and number), then I can evaluate if the number is an valid API version?

 

We can change our versioning, so any suggest will be welcome

2
0 272
Discussion (5)3
Log in or sign up to continue

I would do something like this.

if pVersion?1"v"1n.n {

     // Parameter is well formed vnnn

} else {

     // Parameter is not well formed

}

It's just I need... By this way, I have the version number

Many thanks

Good approach, thanks for your answer.

The methods will be exactly the same as before. The changes in version is a slight change in BP, so I need which version is calling. If I user the version number as parameter, I can add into a message and calls to BP with the version and not replay all methods for each version.

I'll be in mind for future versions.

Thanks

Approach 1

I would be tempted to have your Dispatch class have a forwarding rule for the API version eg v1 or v2 and this will help ensure a clear hierarchical separation both in the URL and in the class definitions between versions. You might also be interested in the %request.URL property for checking relative paths. An example based on your route map might look like 

<Map Prefix="/v1/customer" Forward="MyApp.APIVersion1.Customer" />
<Map Prefix="/v2/customer" Forward="MyApp.
APIVersion2.Customer" />

And your class MyApp.APIVersion1.Customer might look like

<Routes>
        <Route Url="/getcustomer" Method="Post" Call="GetCustomer" />
</Routes>

Personally, I like the classmethod names to reflect the HTTP Method so if I see a GetCustomer method I know that's a HTTP Get method but this is based on personal preference and convention rather than a rule.

Approach 2

The alternative approach is to have everything in the same class but over time this may cause your classes to be rather bloated and unwieldy

<Map Prefix="/v1/customer" Method="Post"  Call="GetCustomerV1" />
<Map Prefix="/v2/customer" Method="Post"  Call="GetCustomerV2" />

Other Thoughts

I do not know if there's a specific function that can be called prior the classmethod in the route map that can validate or invalidate routes. Perhaps the OnPreHTTP method could be used? I noted that some of your methods had the word "default" in them. You can define default route as "/" in your route map.