Skip to content

Router shouldn't handle requests... #113

@ritch

Description

@ritch

@bajtos @superkhau

So our new router is loosely inspired by Express' Router - especially router.handle.

The one thing that never made sense to me is - why is the Router in Express both locating the function to execute and executing it? That really puts the request into a black hole... Instead I think we should do something slightly different (in the spirit of extensibility)...

// loopback core
app.bind(OPERATION, () => {
  const ctx = this;
  return findOperationForContext(ctx);
});

app.bind(RESULT, () => {  
  const ctx = this;
  const args = ctx.get(OPERATION_ARGS);
  const operation = ctx.get(OPERATION);
  const controller = ctx.get(CONTROLLER);
  return operation.apply(controller, args));
});

class Application {
  public async handle(ctx) {
    const result = await ctx.get(RESULT);
    const writer = ctx.get(RESPONSE_WRITER);
    writer(result); // basically res.write(JSON.stringify(result)) 
  }
}

The benefits of this approach is that we build on top of a consistent overridable dependency resolution.

  • You can always rebind what we've bound for you by default (eg. rebind RESULT, OPERATION, anything...) for mocking or extensibility
  • We can add performance, debugging, and other enhancements that will also be picked up by the router if it also uses this same approach

Also consider how this could make it easier to implement extensions eg. Authorization...

app.bind(Bindings.AUTHORIZATION).to(() => {
  const ctx = this;
  const role = await ctx.get('currentUser.role');
  const operation = ctx.get(OPERATION); // <====
  const acl = ctx.get('${operation.name}.acl'); // <====

  for (ctrl of acl) {
    if (ctrl.denies(role) || ctrl.denies(ctx)) return ctrl.denial(ctx);
  }

  return new Authorization(Authorization.DENY, 'you do not have permission to...');
});

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions