Uri advice

#1

We are at a point in our project where we are trying to plan a future safe URI strategy. I'm looking for opinions/advice on the following topics

1. What are the recommendations for a good structure and why?

2. What are the advantages and disadvantages of including dynamic information such as domain and id's in the uri Vs using short and simple URIs and passing information via kwargs instead?

3. How do you recommend handing versioning? included in the uri (v0.getUser) or passed in as an arg or kwarg session.call('user.get', [v0], {id: 123})

Our current considerations are as follows

domain.service.id.action -> com.example.notification.123.get

Vs

V0.getNotifications -> while passing domain and Id information via kwargs

Our thinking is that the first enables the dynamic authorizer the ability to filter access to the uri, while the 2nd version can be named after the method it triggers making it easier for maintenance.

The thing about the dynamic authorizer is that it really only makes sense to filter high level publicky URIs and that protected and private access makes sense to be handled via the various URI end points.

e.g. Accessing v0.getGroup should be approved or denied in the authorizer, however if you have access to the v0.getGroup certain groups could be denied via the end point itself

Does it really makes sense to include dynamic information in the uri for the authorizer or is that simply over complicating them and putting to much burden on one service (the authorizer)

Curious about your thoughts.

0 Likes

#2

bump

regarding versioning we are now considering semantic versioning:

domain.grouping.action.version -> com.example.users.find_user.v1.0.14

our thinking is that embracing semantic versioning in the uris will allow us to deploy multiple uri end points simultaneously which is one of the benefits of micro services.

by placing the version at the end it seems like it would be easier for a client to parse.

wondering though if it will clash with dynamic ids?

we still haven't found much need for dynamic ids in the uri is anyone else using them?

0 Likes

#3

further update.

we have decided not to version or URIs based on the recommendation from Netflix.

instead we are striving for 2 versions, current and future.

we are now experimenting with realms as a means to implement this.

two realms:
production
development

as much as we'd like to use realms for clients current functionality of realms is too limiting.

so we are experimenting with the best pattern for using realms.

we are considering using them for logical separation such as front-end and backend with a connector between the two and or as a means of versioning as noted above.

0 Likes

#4

Hi Greg,

with API versioning, is this what you mean (just to be on the same page, not a solution):

from autobahn import wamp

@wamp.register(u'com.example.greeting@1')
def greeting_v1(name: str) -> str:
     return greeting_v2(1, name)

# API break!
@wamp.register(u'com.example.greeting@2')
@wamp.register(u'com.example.greeting')
def greeting_v2(count: int, name: str) -> str:
     return ('Hello ' + name) * count

···

--

So clients could choose to call the "latest" version "com.example.greeting", or a particular version "com.example.greeting@1".

And older clients (only speaking v1) can run together with new clients (that already know v2), talking to the same backends (which would implement both v1 and v2 as in above).

Is that what you mean with API versioning?

Cheers,
/Tobias

Am 17.04.2016 um 21:28 schrieb Greg Keys:

further update.

we have decided not to version or URIs based on the recommendation from Netflix.

instead we are striving for 2 versions, current and future.

we are now experimenting with realms as a means to implement this.

two realms:
production
development

as much as we'd like to use realms for clients current functionality of realms is too limiting.

so we are experimenting with the best pattern for using realms.

we are considering using them for logical separation such as front-end and backend with a connector between the two and or as a means of versioning as noted above.

0 Likes

#5

I am following this thread as I am interested in the best way to apply versioning to an API as well. From my perspective, I am also leaning away from applying a version identifier in the URI since this seems too rigid.

For our services, we are passing only JSON objects between services, so my current thinking is favoring creating versioned message schemas so the same logical URI handler can accommodate for versions by checking the message schema version #.

···

On Monday, April 18, 2016 at 2:06:35 PM UTC-7, Tobias Oberstein wrote:

Hi Greg,

with API versioning, is this what you mean (just to be on the same page,
not a solution):

from autobahn import wamp

@wamp.register(u’com.example.greeting@1’)

def greeting_v1(name: str) -> str:

 return greeting_v2(1, name)

API break!

@wamp.register(u’com.example.greeting@2’)

@wamp.register(u’com.example.greeting’)

def greeting_v2(count: int, name: str) -> str:

 return ('Hello ' + name) * count

So clients could choose to call the “latest” version
“com.example.greeting”, or a particular version “com.example.greeting@1”.

And older clients (only speaking v1) can run together with new clients
(that already know v2), talking to the same backends (which would
implement both v1 and v2 as in above).

Is that what you mean with API versioning?

Cheers,

/Tobias

Am 17.04.2016 um 21:28 schrieb Greg Keys:

further update.

we have decided not to version or URIs based on the recommendation from Netflix.

instead we are striving for 2 versions, current and future.

we are now experimenting with realms as a means to implement this.

two realms:

production

development

as much as we’d like to use realms for clients current functionality of realms is too limiting.

so we are experimenting with the best pattern for using realms.

we are considering using them for logical separation such as front-end and backend with a connector between the two and or as a means of versioning as noted above.

0 Likes

#6

Hi Greg,

I’m wondering how you ended up with your URI pattern?

did you decide to separate domain via URI and filter on the authorizer or kwargs?

···

On Sunday, January 17, 2016 at 10:27:54 PM UTC+11, Greg Keys wrote:

We are at a point in our project where we are trying to plan a future safe URI strategy. I’m looking for opinions/advice on the following topics

  1. What are the recommendations for a good structure and why?
  1. What are the advantages and disadvantages of including dynamic information such as domain and id’s in the uri Vs using short and simple URIs and passing information via kwargs instead?
  1. How do you recommend handing versioning? included in the uri (v0.getUser) or passed in as an arg or kwarg session.call(‘user.get’, [v0], {id: 123})

Our current considerations are as follows

domain.service.id.action -> com.example.notification.123.get

Vs

V0.getNotifications -> while passing domain and Id information via kwargs

Our thinking is that the first enables the dynamic authorizer the ability to filter access to the uri, while the 2nd version can be named after the method it triggers making it easier for maintenance.

The thing about the dynamic authorizer is that it really only makes sense to filter high level publicky URIs and that protected and private access makes sense to be handled via the various URI end points.

e.g. Accessing v0.getGroup should be approved or denied in the authorizer, however if you have access to the v0.getGroup certain groups could be denied via the end point itself

Does it really makes sense to include dynamic information in the uri for the authorizer or is that simply over complicating them and putting to much burden on one service (the authorizer)

Curious about your thoughts.

0 Likes

#7

Sorry its taken me so long to respond… reasons…

We ended up just hard coding uri’s into our micro services.

we loosely follow a pattern like this: ..

e.g. acme.users.get, acme.users.set or even users.get for a generic service

We opted to not version our uri’s because our services are not multi tenanted, we spin up stacks of services for every customer and every environment (dev, uat, qa, production),

versioning the actual uri would have gotten incredibly difficult to maintain.

I think it might be a good solution for multi-tenanted stacks where you have a single stack of services and need to run 2 or more versions of an api in the same stack.

···

On Thursday, December 7, 2017 at 7:55:16 PM UTC-8, Jan wrote:

Hi Greg,

I’m wondering how you ended up with your URI pattern?

did you decide to separate domain via URI and filter on the authorizer or kwargs?

On Sunday, January 17, 2016 at 10:27:54 PM UTC+11, Greg Keys wrote:

We are at a point in our project where we are trying to plan a future safe URI strategy. I’m looking for opinions/advice on the following topics

  1. What are the recommendations for a good structure and why?
  1. What are the advantages and disadvantages of including dynamic information such as domain and id’s in the uri Vs using short and simple URIs and passing information via kwargs instead?
  1. How do you recommend handing versioning? included in the uri (v0.getUser) or passed in as an arg or kwarg session.call(‘user.get’, [v0], {id: 123})

Our current considerations are as follows

domain.service.id.action -> com.example.notification.123.get

Vs

V0.getNotifications -> while passing domain and Id information via kwargs

Our thinking is that the first enables the dynamic authorizer the ability to filter access to the uri, while the 2nd version can be named after the method it triggers making it easier for maintenance.

The thing about the dynamic authorizer is that it really only makes sense to filter high level publicky URIs and that protected and private access makes sense to be handled via the various URI end points.

e.g. Accessing v0.getGroup should be approved or denied in the authorizer, however if you have access to the v0.getGroup certain groups could be denied via the end point itself

Does it really makes sense to include dynamic information in the uri for the authorizer or is that simply over complicating them and putting to much burden on one service (the authorizer)

Curious about your thoughts.

0 Likes

#8

Thank you for your response Greg.
Also it is very helpful information you described.

···

On Thursday, March 29, 2018 at 5:25:31 PM UTC+11, Greg Keys wrote:

Sorry its taken me so long to respond… reasons…

We ended up just hard coding uri’s into our micro services.

we loosely follow a pattern like this: ..

e.g. acme.users.get, acme.users.set or even users.get for a generic service

We opted to not version our uri’s because our services are not multi tenanted, we spin up stacks of services for every customer and every environment (dev, uat, qa, production),

versioning the actual uri would have gotten incredibly difficult to maintain.

I think it might be a good solution for multi-tenanted stacks where you have a single stack of services and need to run 2 or more versions of an api in the same stack.

On Thursday, December 7, 2017 at 7:55:16 PM UTC-8, Jan wrote:

Hi Greg,

I’m wondering how you ended up with your URI pattern?

did you decide to separate domain via URI and filter on the authorizer or kwargs?

On Sunday, January 17, 2016 at 10:27:54 PM UTC+11, Greg Keys wrote:

We are at a point in our project where we are trying to plan a future safe URI strategy. I’m looking for opinions/advice on the following topics

  1. What are the recommendations for a good structure and why?
  1. What are the advantages and disadvantages of including dynamic information such as domain and id’s in the uri Vs using short and simple URIs and passing information via kwargs instead?
  1. How do you recommend handing versioning? included in the uri (v0.getUser) or passed in as an arg or kwarg session.call(‘user.get’, [v0], {id: 123})

Our current considerations are as follows

domain.service.id.action -> com.example.notification.123.get

Vs

V0.getNotifications -> while passing domain and Id information via kwargs

Our thinking is that the first enables the dynamic authorizer the ability to filter access to the uri, while the 2nd version can be named after the method it triggers making it easier for maintenance.

The thing about the dynamic authorizer is that it really only makes sense to filter high level publicky URIs and that protected and private access makes sense to be handled via the various URI end points.

e.g. Accessing v0.getGroup should be approved or denied in the authorizer, however if you have access to the v0.getGroup certain groups could be denied via the end point itself

Does it really makes sense to include dynamic information in the uri for the authorizer or is that simply over complicating them and putting to much burden on one service (the authorizer)

Curious about your thoughts.

0 Likes