Can a Plugin decide which Route is gonna be called? #126

Open
marloncarvalho opened this Issue Jun 29, 2015 · 3 comments

Comments

Projects
None yet
2 participants
@marloncarvalho

I've been playing around with Redstone for a few days and my goal is to write a Redstone based RESTful API.

To accomplish it, I would like to create a simple mechanism responsible to handle API versioning. I'm thinking about creating an annotation like @Version(version:'v1', strategy: 'header') where the version attribute means the version number and strategy means where this version should be found (in this case, in the Accept header).

This annotation should be used at each class annotated with @Group (note that each route is gonna inherit this version). In that case, it's possible to have two or more classes with the same methods, same signatures and paths but belonging to different versions. Look at the two classes below.

@Group(path: '/myPath')
@Version(version: 'v1', strategy: 'header')
class AVersion1 {

    @Route(path: 'myRoute')
    MyObject get() { ... }
}

@Group(path: '/myPath')
@Version(version: 'v2', strategy: 'header')
class AVersion2 {

    @Route(path: 'myRoute')
    MyObject get() { ... }
}

With that in mind, I should be able to decide, through a plugin, which route to call (from class AVersion1 or AVersionB). Finally, my question is: is it possible?

@marloncarvalho marloncarvalho changed the title from Is it possible to a plugin change the route? to Can a Plugin decide which Route is gonna be called? Jun 29, 2015

@cgarciae

This comment has been minimized.

Show comment
Hide comment
@cgarciae

cgarciae Jun 30, 2015

Contributor

I think one possibility is that you create a class annotation (say ApiGroup) that inherits from Group and just interpolate the version and the urlPrefix onto the Group super constructor. Example

@ApiGroup('/myPath', version: 'v1', strategy: 'header')
class AVersion1 {

    @Route(path: 'myRoute')
    MyObject get() { ... }
}

@ApiGroup('/myPath', version: 'v2', strategy: 'header')
class AVersion2 {

    @Route(path: 'myRoute')
    MyObject get() { ... }
}

The class should be defined something like

class ApiGroup extends Group {
  final String version;
  final String strategy;

  const ApiGroup (String urlPrefix, {this.version: 'v1', this.strategy: 'header'}) : super ('/$version/$urlPrefix');
}

If you are really interested, I already have the GroupController and DataController in redstone_mvc. The DataControllers are there help you with REST, although the only thing they do at the moment is convert the returned objects to JSON. I might be able to implement things into the plugin if you tell me what you are trying to accomplish.

Contributor

cgarciae commented Jun 30, 2015

I think one possibility is that you create a class annotation (say ApiGroup) that inherits from Group and just interpolate the version and the urlPrefix onto the Group super constructor. Example

@ApiGroup('/myPath', version: 'v1', strategy: 'header')
class AVersion1 {

    @Route(path: 'myRoute')
    MyObject get() { ... }
}

@ApiGroup('/myPath', version: 'v2', strategy: 'header')
class AVersion2 {

    @Route(path: 'myRoute')
    MyObject get() { ... }
}

The class should be defined something like

class ApiGroup extends Group {
  final String version;
  final String strategy;

  const ApiGroup (String urlPrefix, {this.version: 'v1', this.strategy: 'header'}) : super ('/$version/$urlPrefix');
}

If you are really interested, I already have the GroupController and DataController in redstone_mvc. The DataControllers are there help you with REST, although the only thing they do at the moment is convert the returned objects to JSON. I might be able to implement things into the plugin if you tell me what you are trying to accomplish.

@marloncarvalho

This comment has been minimized.

Show comment
Hide comment
@marloncarvalho

marloncarvalho Jun 30, 2015

Your approach is only one of two possible ways to control the API versioning. The strategy attribute's goal is to control where the version data should be placed. It would be at the path like in /api/v1/resource or at the Accept header like in application/vnd.vendor.v1+json. However, using your approach the version is going to be fixed at the URL. Agree?

Yesterday, I tried to create a Plugin to figure out whether it's possible or not to create a plugin like that. It turned out that Redstone doesn't allow us to have more than one route with the same path. Consider the example I gave in the first comment. In that example, Redstone only recognizes the routes defined in the class APIVersion2. It ignores the first class or maybe (I'm guessing) it uses a Map and the path as key to this Map and thereby the first class APIVersion1 is replaced by the APIVersion2.

Unfortunately, I think that to achieve my goal, Redstone may have to change some internal implementation.

Your approach is only one of two possible ways to control the API versioning. The strategy attribute's goal is to control where the version data should be placed. It would be at the path like in /api/v1/resource or at the Accept header like in application/vnd.vendor.v1+json. However, using your approach the version is going to be fixed at the URL. Agree?

Yesterday, I tried to create a Plugin to figure out whether it's possible or not to create a plugin like that. It turned out that Redstone doesn't allow us to have more than one route with the same path. Consider the example I gave in the first comment. In that example, Redstone only recognizes the routes defined in the class APIVersion2. It ignores the first class or maybe (I'm guessing) it uses a Map and the path as key to this Map and thereby the first class APIVersion1 is replaced by the APIVersion2.

Unfortunately, I think that to achieve my goal, Redstone may have to change some internal implementation.

@cgarciae

This comment has been minimized.

Show comment
Hide comment
@cgarciae

cgarciae Jul 1, 2015

Contributor

Redstone uses the route_hierarchical to route requests to methods/functions, much of what you see on how both Redstone and Angular manage routing, including route parameter specification style, is because they are based on this library. What you want makes sense given the http guidelines, but requires a routing mechanism that might be beyond what the routing library and redstone (at the moment) are capable.

Contributor

cgarciae commented Jul 1, 2015

Redstone uses the route_hierarchical to route requests to methods/functions, much of what you see on how both Redstone and Angular manage routing, including route parameter specification style, is because they are based on this library. What you want makes sense given the http guidelines, but requires a routing mechanism that might be beyond what the routing library and redstone (at the moment) are capable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment